1 
2 #include "studiox_includes.h"
3 
4 #ifdef _DEBUG
5 #define new DEBUG_NEW
6 #endif
7 
8 
9 static CString right_to_left_language_list[] = {
10 L"Arabic",
11 L"Hebrew",
12 L"Kurdish",
13 L"Persian",
14 L"Urdu",
15 L""
16 };
17 
18 ///////////////////////////////////////////////////////////////////////////////
string_table()19 string_table::string_table()
20 {
21     m_languages = 0;
22     m_active_language = 0;
23     m_sort_column = 0;
24     m_records.SetSize(0, 10);
25     m_dictionary.SetSize(0, 10);
26 }
27 
28 ///////////////////////////////////////////////////////////////////////////////
string_table(const string_table & other)29 string_table::string_table(const string_table &other)
30 {
31     int record;
32     int string;
33 
34     Initialize(other.m_languages, other.m_records.GetCount());
35 
36     for (record = 0; record < m_records.GetCount(); record++)
37     {
38         m_dictionary[record] = other.m_dictionary[record];
39 
40         string_table_record src = other.m_records[record];
41         m_records[record].font_id = src.font_id;
42         m_records[record].id_name = src.id_name;
43         m_records[record].notes = src.notes;
44 
45         for (string = 0; string < m_languages; string++)
46         {
47             m_records[record].strings[string] = src.strings[string];
48             char_map.AddToMap(m_records[record].strings[string]);
49         }
50     }
51     m_sort_column = other.m_sort_column;
52     m_active_language = other.m_active_language;
53 }
54 
55 ///////////////////////////////////////////////////////////////////////////////
~string_table()56 string_table::~string_table()
57 {
58     CleanupStringTable();
59 
60     //Clean up string dictionary
61     m_dictionary.RemoveAll();
62 
63     CleanUpMLViewRefereceRecord();
64 }
65 
66 ///////////////////////////////////////////////////////////////////////////////
IsRight2LeftLanguage(int language_index)67 BOOL string_table::IsRight2LeftLanguage(int language_index)
68 {
69     studiox_project* project = GetOpenProject();
70 
71     if (project)
72     {
73 
74         int index = 0;
75 
76         while (!right_to_left_language_list[index].IsEmpty())
77         {
78             if (right_to_left_language_list[index] == project->mHeader.languages[language_index].name)
79             {
80                 return TRUE;
81             }
82 
83             index++;
84         }
85     }
86 
87     return FALSE;
88 }
89 
90 ///////////////////////////////////////////////////////////////////////////////
EnableDisableRuntimeBidiText(int language_index)91 void string_table::EnableDisableRuntimeBidiText(int language_index)
92 {
93     studiox_project *project = GetOpenProject();
94     if (project->mHeader.languages[language_index].support_bidi_text)
95     {
96         gx_system_bidi_text_enable();
97     }
98     else
99     {
100         gx_system_bidi_text_disable();
101     }
102 }
103 
104 ///////////////////////////////////////////////////////////////////////////////
TestGenerateLanguageDirectionTable()105 BOOL string_table::TestGenerateLanguageDirectionTable()
106 {
107     studiox_project* project = GetOpenProject();
108 
109     if (project && project_lib_version() >= GX_VERSION_BIDI_TEXT_BASE_DIRECTION_FIX)
110     {
111         for (int language = 0; language < project->mHeader.num_languages; language++)
112         {
113             if (project->mHeader.languages[language].support_bidi_text &&
114                 !project->mHeader.languages[language].gen_reordered_bidi_text)
115             {
116                 return TRUE;
117             }
118         }
119     }
120 
121     return FALSE;
122 }
123 
124 ///////////////////////////////////////////////////////////////////////////////
CleanupStringTable()125 void string_table::CleanupStringTable()
126 {
127     int index;
128     char_map.Clear();
129 
130     if (m_records.GetCount() > 0)
131     {
132         for (index = 0; index < m_records.GetCount(); index++)
133         {
134             if (m_records[index].strings)
135             {
136                 delete [] m_records[index].strings;
137             }
138         }
139         m_records.RemoveAll();
140     }
141 
142     m_languages = 0;
143 }
144 
145 ///////////////////////////////////////////////////////////////////////////////
CreateId(CString & id_name,CString base_name)146 void string_table::CreateId(CString &id_name, CString base_name)
147 {
148     CString test;
149     CString num;
150     int val = 1;
151 
152     if (base_name.IsEmpty())
153     {
154         test = CString("STRING_");
155     }
156     else
157     {
158         test = base_name + CString("_");
159     }
160 
161     while(1)
162     {
163         num.Format(_T("%d"), val);
164         id_name = test + num;
165         if (!FindStringIndex(id_name))
166         {
167             return;
168         }
169         val++;
170     }
171 }
172 
173 ///////////////////////////////////////////////////////////////////////////////
Initialize(int num_languages,int num_strings)174 void string_table::Initialize(int num_languages, int num_strings)
175 {
176     CleanupStringTable();
177     m_records.SetSize(num_strings,  10);
178     m_dictionary.SetSize(num_strings, 10);
179 
180     for (int record = 0; record < num_strings; record++)
181     {
182         m_records[record].strings = new CString[num_languages];
183     }
184     m_languages = num_languages;
185 }
186 
187 
188 ///////////////////////////////////////////////////////////////////////////////
AddString(CString & Id,CString & str,bool update_guix)189 int string_table::AddString(CString &Id, CString &str, bool update_guix)
190 {
191     string_table_record record;
192     record.id_name = Id;
193     record.strings = new CString[m_languages];
194     record.strings[0] = str;
195     record.font_id = 0;
196     record.notes = "";
197     m_records.Add(record);
198 
199     AddToDictionary(Id);
200 
201     if (update_guix)
202     {
203         UpdateGuixLanguageTable();
204     }
205 
206     return m_records.GetCount() - 1;
207 }
208 
209 ///////////////////////////////////////////////////////////////////////////////
ImportString(CString & string_id,CString & src_string,CString & target_string,CString & notes,int src_table_column,int target_table_column)210 void string_table::ImportString(CString &string_id,
211                                 CString &src_string,
212                                 CString &target_string,
213                                 CString &notes,
214                                 int src_table_column,
215                                 int target_table_column)
216 {
217     int string_index = FindStringIndex(string_id);
218 
219     if (string_index > 0)
220     {
221         SetString(string_index, target_table_column, target_string, FALSE);
222     }
223     else
224     {
225         string_index = AddString(string_id, CString(""), FALSE);
226         SetString(string_index, src_table_column, src_string, FALSE);
227         SetString(string_index, target_table_column, target_string, FALSE);
228     }
229 
230     SetNotes(string_index, notes);
231 }
232 
233 ///////////////////////////////////////////////////////////////////////////////
AddString()234 int string_table::AddString()
235 {
236     CString NewId;
237     CreateId(NewId);
238     int string_index = AddString(NewId, CString(""));
239     return string_index;
240 }
241 
242 ///////////////////////////////////////////////////////////////////////////////
CheckAddString(CString & str,CString base_name)243 int string_table::CheckAddString(CString &str, CString base_name)
244 {
245     int index;
246     CString NewId;
247 
248     for (index = 1; index < m_records.GetCount(); index++)
249     {
250         if (m_records[index].strings[0] == str)
251         {
252             return index;
253         }
254     }
255 
256     CreateId(NewId, base_name);
257     index = AddString(NewId, str);
258     return index;
259 }
260 
261 ///////////////////////////////////////////////////////////////////////////////
FindStringIndex(CString & id_name)262 int string_table::FindStringIndex(CString &id_name)
263 {
264     int index = 1;
265 
266     while(index < m_records.GetCount())
267     {
268         if (m_records[index].id_name == id_name)
269         {
270             return index;
271         }
272         index++;
273     }
274     return 0;
275 }
276 
277 ///////////////////////////////////////////////////////////////////////////////
RemoveString(CString & id_name)278 void string_table::RemoveString(CString &id_name)
279 {
280     int index = FindStringIndex(id_name);
281     if (index)
282     {
283         RemoveString(index);
284         UpdateGuixLanguageTable();
285     }
286 }
287 
288 ///////////////////////////////////////////////////////////////////////////////
RemoveString(int string_index)289 BOOL string_table::RemoveString(int string_index)
290 {
291     if (string_index >= 0 && string_index < m_records.GetCount())
292     {
293         CString *strings = m_records[string_index].strings;
294 
295         if (strings)
296         {
297             delete [] strings;
298         }
299         RemoveFromDictionary(m_records[string_index].id_name);
300         m_records.RemoveAt(string_index);
301         UpdateGuixLanguageTable();
302         return TRUE;
303     }
304     return FALSE;
305 }
306 
307 ///////////////////////////////////////////////////////////////////////////////
SetString(CString & id_name,int language,CString & str,bool update_guix)308 void string_table::SetString(CString &id_name, int language, CString &str, bool update_guix)
309 {
310     studiox_project *project = GetOpenProject();
311 
312     if (!project)
313     {
314         return;
315     }
316 
317     int index = FindStringIndex(id_name);
318 
319     if (index && language < m_languages)
320     {
321         if (m_records[index].strings[language] != str)
322         {
323             m_records[index].strings[language] = str;
324 
325             if (update_guix)
326             {
327                 UpdateGuixLanguageTable();
328             }
329 
330             int string_id = GetResourceId(id_name);
331             widget_factory::UpdateInputWidgetText(project, string_id);
332         }
333     }
334 }
335 
336 ///////////////////////////////////////////////////////////////////////////////
SetString(int index,CString & id_name,int language,CString & str,bool update_guix)337 void string_table::SetString(int index, CString &id_name, int language, CString &str, bool update_guix)
338 {
339     studiox_project *project = GetOpenProject();
340 
341     if (!project)
342     {
343         return;
344     }
345 
346     if (index >= 0 && index < m_records.GetCount() && language < m_languages)
347     {
348         if (m_records[index].id_name != id_name)
349         {
350             UpdateDictionaryResourceName(m_records[index].id_name, id_name);
351             m_records[index].id_name = id_name;
352         }
353 
354         if (m_records[index].strings[language] != str)
355         {
356             m_records[index].strings[language] = str;
357 
358             if (update_guix)
359             {
360                 UpdateGuixLanguageTable();
361             }
362 
363             int string_id = GetResourceId(id_name);
364             widget_factory::UpdateInputWidgetText(project, string_id);
365         }
366     }
367 }
368 
369 ///////////////////////////////////////////////////////////////////////////////
SetStringId(int string_index,CString & id_name)370 BOOL string_table::SetStringId(int string_index, CString &id_name)
371 {
372     int existing = FindStringIndex(id_name);
373 
374     if (!existing && string_index >= 0 && string_index < m_records.GetCount())
375     {
376         UpdateDictionaryResourceName(m_records[string_index].id_name, id_name);
377         m_records[string_index].id_name = id_name;
378         return TRUE;
379     }
380     return FALSE;
381 }
382 
383 ///////////////////////////////////////////////////////////////////////////////
SetNotes(int string_index,CString & notes)384 void string_table::SetNotes(int string_index, CString &notes)
385 {
386     if (string_index >= 0 && string_index < m_records.GetCount())
387     {
388         m_records[string_index].notes = notes;
389     }
390 }
391 
392 ///////////////////////////////////////////////////////////////////////////////
SetDisplayFont(int string_index,int font_id)393 void string_table::SetDisplayFont(int string_index, int font_id)
394 {
395     if (string_index >= 0 && string_index < m_records.GetCount())
396     {
397         m_records[string_index].font_id = font_id;
398     }
399 }
400 
401 
402 ///////////////////////////////////////////////////////////////////////////////
SetString(int string_index,int language,CString & str,bool update_guix)403 void string_table::SetString(int string_index, int language, CString &str, bool update_guix)
404 {
405     studiox_project *project = GetOpenProject();
406 
407     if (!project)
408     {
409         return;
410     }
411 
412     if (string_index >= 0 && string_index < m_records.GetCount() && language < m_languages)
413     {
414         if (m_records[string_index].strings[language] != str)
415         {
416             m_records[string_index].strings[language] = str;
417 
418             if (update_guix)
419             {
420                 UpdateGuixLanguageTable();
421             }
422 
423             int string_id = GetResourceId(m_records[string_index].id_name);
424             widget_factory::UpdateInputWidgetText(project, string_id);
425         }
426     }
427 }
428 
compare_id(string_table_record * record_1,string_table_record * record_2)429 static int compare_id(string_table_record *record_1, string_table_record *record_2)
430 {
431     return record_1->id_name.Compare(record_2->id_name);
432 }
433 
434 static int language_id;
compare_string(string_table_record * record_1,string_table_record * record_2)435 static int compare_string(string_table_record *record_1, string_table_record *record_2)
436 {
437     return record_1->strings[language_id].Compare(record_2->strings[language_id]);
438 }
439 
440 ///////////////////////////////////////////////////////////////////////////////
SortById()441 void string_table::SortById()
442 {
443     qsort(&m_records.GetAt(1), m_records.GetSize() - 1, sizeof(string_table_record), (int(*)(const void *, const void *))compare_id);
444 }
445 
446 ///////////////////////////////////////////////////////////////////////////////
SortByString()447 void string_table::SortByString()
448 {
449     language_id = m_sort_column - 1;
450     qsort(&m_records.GetAt(1), m_records.GetSize() - 1, sizeof(string_table_record), (int(*)(const void *, const void *))compare_string);
451 }
452 
SortByReferenceCount()453 void string_table::SortByReferenceCount()
454 {
455     studiox_project *project = GetOpenProject();
456 
457     if (project)
458     {
459         int index_1;
460         int index_2;
461         int count_1;
462         int count_2;
463         int resource_id;
464         string_table_record temp;
465 
466         for (index_1 = 1; index_1 < m_records.GetCount() - 1; index_1++)
467         {
468             resource_id = GetResourceId(m_records.GetAt(index_1).id_name);
469             count_1 = widget_factory::CountReferences(project, RES_TYPE_STRING, resource_id);
470 
471             for (index_2 = index_1 + 1; index_2 < m_records.GetCount(); index_2++)
472             {
473                 resource_id = GetResourceId(m_records.GetAt(index_2).id_name);
474                 count_2 = widget_factory::CountReferences(project, RES_TYPE_STRING, resource_id);
475 
476                 if (count_2 < count_1)
477                 {
478                     temp = m_records.GetAt(index_1);
479                     m_records.SetAt(index_1, m_records.GetAt(index_2));
480                     m_records.SetAt(index_2, temp);
481 
482                     count_1 = count_2;
483                 }
484             }
485         }
486     }
487 }
488 
489 ///////////////////////////////////////////////////////////////////////////////
Sort()490 void string_table::Sort()
491 {
492     if ((m_sort_column == -1) || (m_records.GetCount() < 3))
493     {
494         //no sort
495         return;
496     }
497     if (m_sort_column == 0)
498     {
499         SortById();
500     }
501     else if ((m_sort_column >= 1 && m_sort_column <= m_languages))
502     {
503         SortByString();
504     }
505     else if ((m_sort_column == m_languages + 1))
506     {
507         SortByReferenceCount();
508     }
509     else
510     {
511         ErrorMsg("Internal Error: Invalid sorting type.");
512         return;
513     }
514 }
515 
516 CString NullString("");
517 string_table_record NullRecord;
518 
519 ///////////////////////////////////////////////////////////////////////////////
GetRecord(int string_index)520 string_table_record &string_table::GetRecord(int string_index)
521 {
522     if (string_index >= 0 && string_index < m_records.GetCount())
523     {
524         return m_records.GetAt(string_index);
525     }
526     return NullRecord;
527 }
528 
529 ///////////////////////////////////////////////////////////////////////////////
GetRecord(CString id_name)530 string_table_record &string_table::GetRecord(CString id_name)
531 {
532     for (int index = 0; index < m_records.GetCount(); index++)
533     {
534         if (m_records.GetAt(index).id_name == id_name)
535         {
536             return m_records.GetAt(index);
537         }
538     }
539     return NullRecord;
540 }
541 
542 ///////////////////////////////////////////////////////////////////////////////
GetString(CString & id_name,int language)543 CString &string_table::GetString(CString &id_name, int language)
544 {
545     int index = FindStringIndex(id_name);
546 
547     if (index && language < m_languages)
548     {
549         return GetString(index, language);
550     }
551     return NullString;
552 }
553 
554 ///////////////////////////////////////////////////////////////////////////////
GetString(int string_index,int language)555 CString &string_table::GetString(int string_index, int language)
556 {
557     if (string_index >= 0 && string_index < m_records.GetCount() && language < m_languages)
558     {
559         return (m_records[string_index].strings[language]);
560     }
561     return NullString;
562 }
563 
564 ///////////////////////////////////////////////////////////////////////////////
GetStringId(int string_index)565 CString &string_table::GetStringId(int string_index)
566 {
567     if (string_index >= 0 && string_index < m_records.GetCount())
568     {
569         return m_records[string_index].id_name;
570     }
571     return NullString;
572 }
573 
574 ///////////////////////////////////////////////////////////////////////////////
GetNotes(int string_index)575 CString &string_table::GetNotes(int string_index)
576 {
577     if (string_index >= 0 && string_index < m_records.GetCount())
578     {
579         return m_records[string_index].notes;
580     }
581     return NullString;
582 }
583 
584 ///////////////////////////////////////////////////////////////////////////////
CountStrings()585 int string_table::CountStrings()
586 {
587     return (int) m_records.GetCount();
588 }
589 
590 ///////////////////////////////////////////////////////////////////////////////
CountLanguages()591 int string_table::CountLanguages()
592 {
593     return m_languages;
594 }
595 
596 ///////////////////////////////////////////////////////////////////////////////
GenerateCleanCharacterMap()597 FontCharMap *string_table::GenerateCleanCharacterMap()
598 {
599     char_map.Clear();
600 
601     int record;
602     int language;
603 
604     for (record = 0; record < m_records.GetCount(); record++)
605     {
606         for (language = 0; language < m_languages; language++)
607         {
608             if (!m_records[record].strings[language].IsEmpty())
609             {
610                 char_map.AddToMap(m_records[record].strings[language]);
611             }
612         }
613     }
614     return &char_map;
615 }
616 
617 // This function builds a string table for GUIX and installs it
618 // using this object's data. First, it makes sure that this
619 // table is the active string table being displayed by GUIX
620 
621 ///////////////////////////////////////////////////////////////////////////////
UpdateGuixLanguageTable(GX_DISPLAY * Display,BOOL update_resource_view)622 void string_table::UpdateGuixLanguageTable(GX_DISPLAY *Display, BOOL update_resource_view)
623 {
624     // first, make certain that this table instance is the one
625     // that is actively used by GUIX:
626     studiox_project *project = GetOpenProject();
627     if (!project)
628     {
629         return;
630     }
631     int display = GetProjectView()->GetActiveDisplay();
632 
633     if (display < 0)
634     {
635         return;
636     }
637     if (project->mDisplays[display].stable != this)
638     {
639       return;
640     }
641 
642     // yes, this table is the active table being displayed.
643     // keep pointer to old table to delete later:
644     GX_STRING **pOldTable;
645     GX_UBYTE old_language_count;
646     UINT old_string_count;
647     int StringId;
648     int language;
649 
650     if (!Display)
651     {
652         Display = get_target_view_display();
653     }
654 
655     gx_display_language_table_get_ext(Display, &pOldTable, &old_language_count, &old_string_count);
656 
657     GX_UBYTE *pDirectionTable = new GX_UBYTE[m_languages];
658     GX_STRING **pLangTable = new GX_STRING *[m_languages];
659     memset(pLangTable, 0, m_languages * sizeof(GX_STRING *));
660     BOOL new_char = FALSE;
661     string_table_record record;
662     CString InString;
663 
664     for (language = 0; language < m_languages; language++)
665     {
666         GX_STRING *pStringTable = new GX_STRING[m_dictionary.GetCount()];
667         pStringTable[0].gx_string_ptr = NULL;
668         pStringTable[0].gx_string_length = 0;
669 
670         pLangTable[language] = pStringTable;
671 
672         if (string_table::IsRight2LeftLanguage(language))
673         {
674             pDirectionTable[language] = GX_LANGUAGE_DIRECTION_RTL;
675         }
676         else
677         {
678             pDirectionTable[language] = GX_LANGUAGE_DIRECTION_LTR;
679         }
680 
681         for (StringId = 1; StringId < m_dictionary.GetCount(); StringId++)
682         {
683             record = GetRecord(GetResourceIdName(StringId));
684             InString = record.strings[language];
685 
686             if (InString.IsEmpty())
687             {
688                 pStringTable[StringId].gx_string_ptr = NULL;
689                 pStringTable[StringId].gx_string_length = 0;
690             }
691             else
692             {
693                 if (char_map.AddToMap(InString))
694                 {
695                     new_char = TRUE;
696                 }
697                 resource_gen::MakeUtf8String(project, InString, language, &pStringTable[StringId], display, FALSE);
698             }
699         }
700     }
701 
702     if (new_char)
703     {
704         SendMessage(GetResourceView()->GetSafeHwnd(), USR_MSG_UPDATE_STRING_TABLE_FONTS, (WPARAM)&char_map, 0);
705     }
706 
707     gx_display_language_table_set_ext(Display, (GX_CONST GX_STRING **) pLangTable, m_languages, (UINT)m_records.GetCount());
708 
709     // delete old direction table
710     DeleteGuixLanguageDirectionTable(Display);
711 
712     gx_display_language_direction_table_set(Display, (GX_CONST GX_UBYTE *)pDirectionTable, m_languages);
713 
714     // now delete the old table:
715 
716     DeleteGuixLanguageTable(pOldTable, old_language_count, old_string_count);
717 
718     if (update_resource_view)
719     {
720         // now tell the resource view about the new string table:
721         SendMessage(GetResourceView()->GetSafeHwnd(), USR_MSG_REBUILD_STIRNG_ITEMS, (WPARAM)FALSE, 0);
722     }
723 }
724 
725 ///////////////////////////////////////////////////////////////////////////////
DeleteGuixLanguageDirectionTable(GX_DISPLAY * display)726 void string_table::DeleteGuixLanguageDirectionTable(GX_DISPLAY* display)
727 {
728     if (display->gx_display_language_direction_table)
729     {
730         delete display->gx_display_language_direction_table;
731         display->gx_display_language_direction_table = NULL;
732     }
733 }
734 
735 ///////////////////////////////////////////////////////////////////////////////
DeleteGuixLanguageTable(GX_STRING ** pOldTable,int language_count,int string_count)736 void string_table::DeleteGuixLanguageTable(GX_STRING **pOldTable, int language_count, int string_count)
737 {
738     INT StringId;
739     INT language;
740     GX_STRING *pStringTable;
741 
742     if (pOldTable && language_count > 0)
743     {
744         for (language = 0; language < language_count; language++)
745         {
746             pStringTable = pOldTable[language];
747 
748             if (pStringTable)
749             {
750                 for (StringId = 0; StringId < string_count; StringId++)
751                 {
752                     if (pStringTable[StringId].gx_string_ptr)
753                     {
754                         delete [] pStringTable[StringId].gx_string_ptr;
755                         pStringTable[StringId].gx_string_ptr = NULL;
756                         pStringTable[StringId].gx_string_length = 0;
757                     }
758                 }
759                 delete [] pStringTable;
760                 pOldTable[language] = NULL;
761             }
762         }
763         delete [] pOldTable;
764     }
765 }
766 
767 ///////////////////////////////////////////////////////////////////////////////
AddToDictionary(CString & id_name,int res_id)768 void string_table::AddToDictionary(CString &id_name, int res_id)
769 {
770     if (res_id == -1)
771     {
772         m_dictionary.Add(id_name);
773     }
774     else
775     {
776         m_dictionary.SetAtGrow(res_id, id_name);
777     }
778 }
779 
780 ///////////////////////////////////////////////////////////////////////////////
RemoveFromDictionary(CString & id_name)781 void string_table::RemoveFromDictionary(CString &id_name)
782 {
783     for (int index = 1; index < m_dictionary.GetCount(); index++)
784     {
785         if (m_dictionary.GetAt(index) == id_name)
786         {
787             m_dictionary.RemoveAt(index);
788             return;
789         }
790     }
791 }
792 
793 ///////////////////////////////////////////////////////////////////////////////
UpdateRichTextResourceName(CString & val,int res_type,CString old_id_name,CString new_id_name)794 CString string_table::UpdateRichTextResourceName(CString& val, int res_type, CString old_id_name, CString new_id_name)
795 {
796     CString out("");
797     CString tag;
798     CString id_name;
799     int index = 0;
800 
801     if (res_type == RES_TYPE_FONT)
802     {
803         old_id_name.Insert(0, _T("GX_FONT_ID_"));
804         new_id_name.Insert(0, _T("GX_FONT_ID_"));
805     }
806     else
807     {
808         old_id_name.Insert(0, _T("GX_COLOR_ID_"));
809         new_id_name.Insert(0, _T("GX_COLOR_ID_"));
810     }
811 
812     while (1)
813     {
814         // Find tag start flag
815         index = val.Find('<');
816 
817         if (index >= 0)
818         {
819             out.Append(val.Left(index + 1));
820             val = val.Mid(index + 1);
821 
822             index = val.Find(_T(" "));
823 
824             if (index >= 0)
825             {
826                 // Get tag
827                 tag = val.Left(index);
828 
829                 if ((tag != "f") && (tag != "c") && (tag != "hc"))
830                 {
831                     continue;
832                 }
833 
834                 out.Append(val.Left(index + 1));
835                 val = val.Mid(index + 1);
836 
837                 index = val.Find(_T(">"));
838                 if (index >= 0)
839                 {
840                     // Get resource id name
841                     id_name = val.Left(index);
842 
843                     if (id_name == old_id_name)
844                     {
845                         val = val.Mid(index + 1);
846                         out.Append(new_id_name);
847                         out.Append(_T(">"));
848                     }
849                 }
850             }
851         }
852         else
853         {
854             out.Append(val);
855             break;
856         }
857     }
858 
859     return out;
860 }
861 
862 ///////////////////////////////////////////////////////////////////////////////
UpdateStringTableRichTextResourceName(int res_type,CString & old_id_name,CString & new_id_name)863 void string_table::UpdateStringTableRichTextResourceName(int res_type, CString& old_id_name, CString& new_id_name)
864 {
865     int num_strings = m_records.GetCount();
866 
867     for (int record = 0; record < num_strings; record++)
868     {
869         for (int language = 0; language < m_languages; language++)
870         {
871             if (!m_records[record].strings[language].IsEmpty())
872             {
873                 m_records[record].strings[language] = UpdateRichTextResourceName(m_records[record].strings[language], res_type, old_id_name, new_id_name);
874             }
875         }
876     }
877 }
878 
879 ///////////////////////////////////////////////////////////////////////////////
UpdateDictionaryResourceName(CString & old_id_name,CString & new_id_name)880 void string_table::UpdateDictionaryResourceName(CString& old_id_name, CString& new_id_name)
881 {
882     for (int index = 1; index < m_dictionary.GetCount(); index++)
883     {
884         if (m_dictionary.GetAt(index) == old_id_name)
885         {
886             m_dictionary.SetAt(index, new_id_name);
887             return;
888         }
889     }
890 }
891 
892 ///////////////////////////////////////////////////////////////////////////////
GetResourceIdName(int res_id,widget_info * info)893 CString string_table::GetResourceIdName(int res_id, widget_info* info)
894 {
895     CString id_name("");
896 
897     if (res_id > 0 && res_id < m_dictionary.GetCount())
898     {
899         id_name = m_dictionary.GetAt(res_id);
900     }
901 
902     if (info)
903     {
904         string_reference_record *record = GetMLViewReferenceRecord(id_name);
905 
906         if (record)
907         {
908             for (int index = 0; index < record->reference_list.GetCount(); index++)
909             {
910                 if ((record->reference_list.GetAt(index) == info) && (record->reference_list.GetCount() > 1))
911                 {
912                     id_name.Format(L"%s_%s", id_name, info->app_name);
913                     id_name.MakeUpper();
914                     if (FindStringIndex(id_name))
915                     {
916                         CreateId(id_name, id_name);
917                     }
918                 }
919             }
920         }
921     }
922 
923     return id_name;
924 }
925 
926 ///////////////////////////////////////////////////////////////////////////////
GetResourceId(CString & id_name)927 GX_RESOURCE_ID string_table::GetResourceId(CString& id_name)
928 {
929     for (int index = 1; index < m_dictionary.GetCount(); index++)
930     {
931         if (m_dictionary.GetAt(index) == id_name)
932         {
933             return index;
934         }
935     }
936 
937     return 0;
938 }
939 
940 
941 ////////////////////////////////////////////////////////////////////////////////////////////////
MakeMLViewReferenceRecord(widget_info * child)942 bool string_table::MakeMLViewReferenceRecord(widget_info* child)
943 {
944     string_reference_record* record;
945     CString id_name;
946 
947     while (child)
948     {
949         if ((child->basetype == GX_TYPE_MULTI_LINE_TEXT_VIEW) && child->string_id[0])
950         {
951             id_name = GetResourceIdName(child->string_id[0]);
952             record = GetMLViewReferenceRecord(id_name);
953 
954             if (record)
955             {
956                 record->reference_list.Add(child);
957             }
958             else
959             {
960                 record = new string_reference_record;
961                 record->id_name = id_name;
962                 record->reference_list.Add(child);
963                 m_reference_records.Add(record);
964             }
965         }
966 
967         MakeMLViewReferenceRecord(child->GetChildWidgetInfo());
968 
969         child = child->GetNextWidgetInfo();
970     }
971 
972     return FALSE;
973 }
974 
975 ////////////////////////////////////////////////////////////////////////////////////////////////
MakeMLViewReferenceRecord(int display)976 void string_table::MakeMLViewReferenceRecord(int display)
977 {
978     studiox_project *project = GetOpenProject();
979     bool generate_unique_reference = FALSE;
980 
981     for (int lang = 0; lang < project->mHeader.num_languages; lang++)
982     {
983         if (project->mHeader.languages[lang].support_bidi_text &&
984             project->mHeader.languages[lang].gen_reordered_bidi_text)
985         {
986             generate_unique_reference = TRUE;
987             break;
988         }
989     }
990 
991     if (!generate_unique_reference)
992     {
993         return;
994     }
995 
996     // Clear reference record.
997     CleanUpMLViewRefereceRecord();
998 
999     // Make reference record.
1000     folder_info *folder;
1001 
1002     folder = project->mDisplays[display].GetFirstChildFolder();
1003     while (folder)
1004     {
1005         MakeMLViewReferenceRecord(folder->GetFirstChildWidget());
1006 
1007         folder = folder->GetNextFolder();
1008     }
1009 }
1010 
1011 ///////////////////////////////////////////////////////////////////////////////
CleanUpMLViewRefereceRecord()1012 void string_table::CleanUpMLViewRefereceRecord()
1013 {
1014     string_reference_record* record = NULL;
1015 
1016     for (int index = 0; index < m_reference_records.GetCount(); index++)
1017     {
1018         record = m_reference_records.GetAt(index);
1019         delete record;
1020     }
1021 
1022     m_reference_records.RemoveAll();
1023 }
1024 
1025 ///////////////////////////////////////////////////////////////////////////////
GetMLViewReferenceRecord(CString & id_name)1026 string_reference_record * string_table::GetMLViewReferenceRecord(CString& id_name)
1027 {
1028     string_reference_record *record = NULL;
1029 
1030     for (int index = 0; index < m_reference_records.GetCount(); index++)
1031     {
1032         record = m_reference_records.GetAt(index);
1033         if (record->id_name == id_name)
1034         {
1035             return record;
1036         }
1037     }
1038 
1039     return NULL;
1040 }
1041 
1042 ///////////////////////////////////////////////////////////////////////////////
GetMLViewReferenceWidgetInfoList(CString & id_name)1043 CArray<widget_info *> *string_table::GetMLViewReferenceWidgetInfoList(CString& id_name)
1044 {
1045     string_reference_record* record = GetMLViewReferenceRecord(id_name);
1046 
1047     if (record)
1048     {
1049         return &record->reference_list;
1050     }
1051 
1052     return NULL;
1053 }
1054 
1055 ///////////////////////////////////////////////////////////////////////////////
CountGeneratedStrings()1056 int string_table::CountGeneratedStrings()
1057 {
1058     string_reference_record* record;
1059     int count = CountStrings();
1060 
1061     for (int index = 0; index < m_reference_records.GetCount(); index++)
1062     {
1063         record = m_reference_records.GetAt(index);
1064         count += (record->reference_list.GetCount() - 1);
1065     }
1066 
1067     return count;
1068 }
1069 
1070 ///////////////////////////////////////////////////////////////////////////////
AddLanguage()1071 void string_table::AddLanguage()
1072 {
1073     int old_languages = m_languages;
1074     m_languages++;
1075     int num_strings = m_records.GetCount();
1076 
1077     for (int record = 0; record < num_strings; record++)
1078     {
1079         CString *old_strings = m_records[record].strings;
1080         m_records[record].strings = new CString[m_languages];
1081 
1082         for (int language = 0; language < old_languages; language++)
1083         {
1084             if (!old_strings[language].IsEmpty())
1085             {
1086                 m_records[record].strings[language] = old_strings[language];
1087             }
1088         }
1089         delete [] old_strings;
1090     }
1091 }
1092 
1093 ///////////////////////////////////////////////////////////////////////////////
SetActiveLanguage(int language)1094 void string_table::SetActiveLanguage(int language)
1095 {
1096     studiox_project* project = GetOpenProject();
1097 
1098     if (!project)
1099     {
1100         return;
1101     }
1102 
1103     m_active_language = language;
1104 
1105     GX_DISPLAY* display = get_target_view_display();
1106 
1107     if (!display)
1108     {
1109         return;
1110     }
1111 
1112     if (language >= display->gx_display_language_table_size)
1113     {
1114         UpdateGuixLanguageTable();
1115     }
1116     gx_display_active_language_set(display, language);
1117     EnableDisableRuntimeBidiText(language);
1118 }