Code

Translations. French translation minor update.
[inkscape.git] / src / ui / dialog / glyphs.cpp
1 /**
2  * Glyph selector dialog.
3  */
5 /* Authors:
6  *   Jon A. Cruz
7  *   Abhishek Sharma
8  *
9  * Copyright (C) 2010 Jon A. Cruz
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #include <vector>
15 #include <glibmm/i18n.h>
16 #include <gtkmm/entry.h>
17 #include <gtkmm/iconview.h>
18 #include <gtkmm/label.h>
19 #include <gtkmm/liststore.h>
20 #include <gtkmm/scrolledwindow.h>
21 #include <gtkmm/table.h>
22 #include <gtkmm/treemodelcolumn.h>
23 #include <gtkmm/widget.h>
25 #include <gtk/gtkbutton.h>
26 #include <gtk/gtkstock.h>
27 #include <gtk/gtkversion.h>
29 #include "glyphs.h"
31 #include "desktop.h"
32 #include "document.h" // for SPDocumentUndo::done()
33 #include "libnrtype/font-instance.h"
34 #include "sp-flowtext.h"
35 #include "sp-text.h"
36 #include "verbs.h"
37 #include "widgets/font-selector.h"
38 #include "text-editing.h"
40 namespace Inkscape {
41 namespace UI {
42 namespace Dialog {
45 GlyphsPanel &GlyphsPanel::getInstance()
46 {
47     return *new GlyphsPanel();
48 }
51 #if GLIB_CHECK_VERSION(2,14,0)
52 static std::map<GUnicodeScript, Glib::ustring> & getScriptToName()
53 {
54     static bool init = false;
55     static std::map<GUnicodeScript, Glib::ustring> mappings;
56     if (!init) {
57         init = true;
58         mappings[G_UNICODE_SCRIPT_INVALID_CODE]         = _("all");
59         mappings[G_UNICODE_SCRIPT_COMMON]               = _("common");
60         mappings[G_UNICODE_SCRIPT_INHERITED]            = _("inherited");
61         mappings[G_UNICODE_SCRIPT_ARABIC]               = _("Arabic");
62         mappings[G_UNICODE_SCRIPT_ARMENIAN]             = _("Armenian");
63         mappings[G_UNICODE_SCRIPT_BENGALI]              = _("Bengali");
64         mappings[G_UNICODE_SCRIPT_BOPOMOFO]             = _("Bopomofo");
65         mappings[G_UNICODE_SCRIPT_CHEROKEE]             = _("Cherokee");
66         mappings[G_UNICODE_SCRIPT_COPTIC]               = _("Coptic");
67         mappings[G_UNICODE_SCRIPT_CYRILLIC]             = _("Cyrillic");
68         mappings[G_UNICODE_SCRIPT_DESERET]              = _("Deseret");
69         mappings[G_UNICODE_SCRIPT_DEVANAGARI]           = _("Devanagari");
70         mappings[G_UNICODE_SCRIPT_ETHIOPIC]             = _("Ethiopic");
71         mappings[G_UNICODE_SCRIPT_GEORGIAN]             = _("Georgian");
72         mappings[G_UNICODE_SCRIPT_GOTHIC]               = _("Gothic");
73         mappings[G_UNICODE_SCRIPT_GREEK]                = _("Greek");
74         mappings[G_UNICODE_SCRIPT_GUJARATI]             = _("Gujarati");
75         mappings[G_UNICODE_SCRIPT_GURMUKHI]             = _("Gurmukhi");
76         mappings[G_UNICODE_SCRIPT_HAN]                  = _("Han");
77         mappings[G_UNICODE_SCRIPT_HANGUL]               = _("Hangul");
78         mappings[G_UNICODE_SCRIPT_HEBREW]               = _("Hebrew");
79         mappings[G_UNICODE_SCRIPT_HIRAGANA]             = _("Hiragana");
80         mappings[G_UNICODE_SCRIPT_KANNADA]              = _("Kannada");
81         mappings[G_UNICODE_SCRIPT_KATAKANA]             = _("Katakana");
82         mappings[G_UNICODE_SCRIPT_KHMER]                = _("Khmer");
83         mappings[G_UNICODE_SCRIPT_LAO]                  = _("Lao");
84         mappings[G_UNICODE_SCRIPT_LATIN]                = _("Latin");
85         mappings[G_UNICODE_SCRIPT_MALAYALAM]            = _("Malayalam");
86         mappings[G_UNICODE_SCRIPT_MONGOLIAN]            = _("Mongolian");
87         mappings[G_UNICODE_SCRIPT_MYANMAR]              = _("Myanmar");
88         mappings[G_UNICODE_SCRIPT_OGHAM]                = _("Ogham");
89         mappings[G_UNICODE_SCRIPT_OLD_ITALIC]           = _("Old Italic");
90         mappings[G_UNICODE_SCRIPT_ORIYA]                = _("Oriya");
91         mappings[G_UNICODE_SCRIPT_RUNIC]                = _("Runic");
92         mappings[G_UNICODE_SCRIPT_SINHALA]              = _("Sinhala");
93         mappings[G_UNICODE_SCRIPT_SYRIAC]               = _("Syriac");
94         mappings[G_UNICODE_SCRIPT_TAMIL]                = _("Tamil");
95         mappings[G_UNICODE_SCRIPT_TELUGU]               = _("Telugu");
96         mappings[G_UNICODE_SCRIPT_THAANA]               = _("Thaana");
97         mappings[G_UNICODE_SCRIPT_THAI]                 = _("Thai");
98         mappings[G_UNICODE_SCRIPT_TIBETAN]              = _("Tibetan");
99         mappings[G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL]  = _("Canadian Aboriginal");
100         mappings[G_UNICODE_SCRIPT_YI]                   = _("Yi");
101         mappings[G_UNICODE_SCRIPT_TAGALOG]              = _("Tagalog");
102         mappings[G_UNICODE_SCRIPT_HANUNOO]              = _("Hanunoo");
103         mappings[G_UNICODE_SCRIPT_BUHID]                = _("Buhid");
104         mappings[G_UNICODE_SCRIPT_TAGBANWA]             = _("Tagbanwa");
105         mappings[G_UNICODE_SCRIPT_BRAILLE]              = _("Braille");
106         mappings[G_UNICODE_SCRIPT_CYPRIOT]              = _("Cypriot");
107         mappings[G_UNICODE_SCRIPT_LIMBU]                = _("Limbu");
108         mappings[G_UNICODE_SCRIPT_OSMANYA]              = _("Osmanya");
109         mappings[G_UNICODE_SCRIPT_SHAVIAN]              = _("Shavian");
110         mappings[G_UNICODE_SCRIPT_LINEAR_B]             = _("Linear B");
111         mappings[G_UNICODE_SCRIPT_TAI_LE]               = _("Tai Le");
112         mappings[G_UNICODE_SCRIPT_UGARITIC]             = _("Ugaritic");
113         mappings[G_UNICODE_SCRIPT_NEW_TAI_LUE]          = _("New Tai Lue");
114         mappings[G_UNICODE_SCRIPT_BUGINESE]             = _("Buginese");
115         mappings[G_UNICODE_SCRIPT_GLAGOLITIC]           = _("Glagolitic");
116         mappings[G_UNICODE_SCRIPT_TIFINAGH]             = _("Tifinagh");
117         mappings[G_UNICODE_SCRIPT_SYLOTI_NAGRI]         = _("Syloti Nagri");
118         mappings[G_UNICODE_SCRIPT_OLD_PERSIAN]          = _("Old Persian");
119         mappings[G_UNICODE_SCRIPT_KHAROSHTHI]           = _("Kharoshthi");
120         mappings[G_UNICODE_SCRIPT_UNKNOWN]              = _("unassigned");
121         mappings[G_UNICODE_SCRIPT_BALINESE]             = _("Balinese");
122         mappings[G_UNICODE_SCRIPT_CUNEIFORM]            = _("Cuneiform");
123         mappings[G_UNICODE_SCRIPT_PHOENICIAN]           = _("Phoenician");
124         mappings[G_UNICODE_SCRIPT_PHAGS_PA]             = _("Phags-pa");
125         mappings[G_UNICODE_SCRIPT_NKO]                  = _("N'Ko");
127 #if GLIB_CHECK_VERSION(2,14,0)
128         mappings[G_UNICODE_SCRIPT_KAYAH_LI]             = _("Kayah Li");
129         mappings[G_UNICODE_SCRIPT_LEPCHA]               = _("Lepcha");
130         mappings[G_UNICODE_SCRIPT_REJANG]               = _("Rejang");
131         mappings[G_UNICODE_SCRIPT_SUNDANESE]            = _("Sundanese");
132         mappings[G_UNICODE_SCRIPT_SAURASHTRA]           = _("Saurashtra");
133         mappings[G_UNICODE_SCRIPT_CHAM]                 = _("Cham");
134         mappings[G_UNICODE_SCRIPT_OL_CHIKI]             = _("Ol Chiki");
135         mappings[G_UNICODE_SCRIPT_VAI]                  = _("Vai");
136         mappings[G_UNICODE_SCRIPT_CARIAN]               = _("Carian");
137         mappings[G_UNICODE_SCRIPT_LYCIAN]               = _("Lycian");
138         mappings[G_UNICODE_SCRIPT_LYDIAN]               = _("Lydian");
139 #endif // GLIB_CHECK_VERSION(2,14,0)
140     }
141     return mappings;
143 #endif // GLIB_CHECK_VERSION(2,14,0)
145 typedef std::pair<gunichar, gunichar> Range;
146 typedef std::pair<Range, Glib::ustring> NamedRange;
148 static std::vector<NamedRange> & getRanges()
150     static bool init = false;
151     static std::vector<NamedRange> ranges;
152     if (!init) {
153         init = true;
154         ranges.push_back(std::make_pair(std::make_pair(0x0000, 0xFFFD), _("all")));
155         ranges.push_back(std::make_pair(std::make_pair(0x0000, 0x007F), _("Basic Latin")));
156         ranges.push_back(std::make_pair(std::make_pair(0x0080, 0x00FF), _("Latin-1 Supplement")));
157         ranges.push_back(std::make_pair(std::make_pair(0x0100, 0x017F), _("Latin Extended-A")));
158         ranges.push_back(std::make_pair(std::make_pair(0x0180, 0x024F), _("Latin Extended-B")));
159         ranges.push_back(std::make_pair(std::make_pair(0x0250, 0x02AF), _("IPA Extensions")));
160         ranges.push_back(std::make_pair(std::make_pair(0x02B0, 0x02FF), _("Spacing Modifier Letters")));
161         ranges.push_back(std::make_pair(std::make_pair(0x0300, 0x036F), _("Combining Diacritical Marks")));
162         ranges.push_back(std::make_pair(std::make_pair(0x0370, 0x03FF), _("Greek and Coptic")));
163         ranges.push_back(std::make_pair(std::make_pair(0x0400, 0x04FF), _("Cyrillic")));
164         ranges.push_back(std::make_pair(std::make_pair(0x0500, 0x052F), _("Cyrillic Supplement")));
165         ranges.push_back(std::make_pair(std::make_pair(0x0530, 0x058F), _("Armenian")));
166         ranges.push_back(std::make_pair(std::make_pair(0x0590, 0x05FF), _("Hebrew")));
167         ranges.push_back(std::make_pair(std::make_pair(0x0600, 0x06FF), _("Arabic")));
168         ranges.push_back(std::make_pair(std::make_pair(0x0700, 0x074F), _("Syriac")));
169         ranges.push_back(std::make_pair(std::make_pair(0x0750, 0x077F), _("Arabic Supplement")));
170         ranges.push_back(std::make_pair(std::make_pair(0x0780, 0x07BF), _("Thaana")));
171         ranges.push_back(std::make_pair(std::make_pair(0x07C0, 0x07FF), _("NKo")));
172         ranges.push_back(std::make_pair(std::make_pair(0x0800, 0x083F), _("Samaritan")));
173         ranges.push_back(std::make_pair(std::make_pair(0x0900, 0x097F), _("Devanagari")));
174         ranges.push_back(std::make_pair(std::make_pair(0x0980, 0x09FF), _("Bengali")));
175         ranges.push_back(std::make_pair(std::make_pair(0x0A00, 0x0A7F), _("Gurmukhi")));
176         ranges.push_back(std::make_pair(std::make_pair(0x0A80, 0x0AFF), _("Gujarati")));
177         ranges.push_back(std::make_pair(std::make_pair(0x0B00, 0x0B7F), _("Oriya")));
178         ranges.push_back(std::make_pair(std::make_pair(0x0B80, 0x0BFF), _("Tamil")));
179         ranges.push_back(std::make_pair(std::make_pair(0x0C00, 0x0C7F), _("Telugu")));
180         ranges.push_back(std::make_pair(std::make_pair(0x0C80, 0x0CFF), _("Kannada")));
181         ranges.push_back(std::make_pair(std::make_pair(0x0D00, 0x0D7F), _("Malayalam")));
182         ranges.push_back(std::make_pair(std::make_pair(0x0D80, 0x0DFF), _("Sinhala")));
183         ranges.push_back(std::make_pair(std::make_pair(0x0E00, 0x0E7F), _("Thai")));
184         ranges.push_back(std::make_pair(std::make_pair(0x0E80, 0x0EFF), _("Lao")));
185         ranges.push_back(std::make_pair(std::make_pair(0x0F00, 0x0FFF), _("Tibetan")));
186         ranges.push_back(std::make_pair(std::make_pair(0x1000, 0x109F), _("Myanmar")));
187         ranges.push_back(std::make_pair(std::make_pair(0x10A0, 0x10FF), _("Georgian")));
188         ranges.push_back(std::make_pair(std::make_pair(0x1100, 0x11FF), _("Hangul Jamo")));
189         ranges.push_back(std::make_pair(std::make_pair(0x1200, 0x137F), _("Ethiopic")));
190         ranges.push_back(std::make_pair(std::make_pair(0x1380, 0x139F), _("Ethiopic Supplement")));
191         ranges.push_back(std::make_pair(std::make_pair(0x13A0, 0x13FF), _("Cherokee")));
192         ranges.push_back(std::make_pair(std::make_pair(0x1400, 0x167F), _("Unified Canadian Aboriginal Syllabics")));
193         ranges.push_back(std::make_pair(std::make_pair(0x1680, 0x169F), _("Ogham")));
194         ranges.push_back(std::make_pair(std::make_pair(0x16A0, 0x16FF), _("Runic")));
195         ranges.push_back(std::make_pair(std::make_pair(0x1700, 0x171F), _("Tagalog")));
196         ranges.push_back(std::make_pair(std::make_pair(0x1720, 0x173F), _("Hanunoo")));
197         ranges.push_back(std::make_pair(std::make_pair(0x1740, 0x175F), _("Buhid")));
198         ranges.push_back(std::make_pair(std::make_pair(0x1760, 0x177F), _("Tagbanwa")));
199         ranges.push_back(std::make_pair(std::make_pair(0x1780, 0x17FF), _("Khmer")));
200         ranges.push_back(std::make_pair(std::make_pair(0x1800, 0x18AF), _("Mongolian")));
201         ranges.push_back(std::make_pair(std::make_pair(0x18B0, 0x18FF), _("Unified Canadian Aboriginal Syllabics Extended")));
202         ranges.push_back(std::make_pair(std::make_pair(0x1900, 0x194F), _("Limbu")));
203         ranges.push_back(std::make_pair(std::make_pair(0x1950, 0x197F), _("Tai Le")));
204         ranges.push_back(std::make_pair(std::make_pair(0x1980, 0x19DF), _("New Tai Lue")));
205         ranges.push_back(std::make_pair(std::make_pair(0x19E0, 0x19FF), _("Khmer Symbols")));
206         ranges.push_back(std::make_pair(std::make_pair(0x1A00, 0x1A1F), _("Buginese")));
207         ranges.push_back(std::make_pair(std::make_pair(0x1A20, 0x1AAF), _("Tai Tham")));
208         ranges.push_back(std::make_pair(std::make_pair(0x1B00, 0x1B7F), _("Balinese")));
209         ranges.push_back(std::make_pair(std::make_pair(0x1B80, 0x1BBF), _("Sundanese")));
210         ranges.push_back(std::make_pair(std::make_pair(0x1C00, 0x1C4F), _("Lepcha")));
211         ranges.push_back(std::make_pair(std::make_pair(0x1C50, 0x1C7F), _("Ol Chiki")));
212         ranges.push_back(std::make_pair(std::make_pair(0x1CD0, 0x1CFF), _("Vedic Extensions")));
213         ranges.push_back(std::make_pair(std::make_pair(0x1D00, 0x1D7F), _("Phonetic Extensions")));
214         ranges.push_back(std::make_pair(std::make_pair(0x1D80, 0x1DBF), _("Phonetic Extensions Supplement")));
215         ranges.push_back(std::make_pair(std::make_pair(0x1DC0, 0x1DFF), _("Combining Diacritical Marks Supplement")));
216         ranges.push_back(std::make_pair(std::make_pair(0x1E00, 0x1EFF), _("Latin Extended Additional")));
217         ranges.push_back(std::make_pair(std::make_pair(0x1F00, 0x1FFF), _("Greek Extended")));
218         ranges.push_back(std::make_pair(std::make_pair(0x2000, 0x206F), _("General Punctuation")));
219         ranges.push_back(std::make_pair(std::make_pair(0x2070, 0x209F), _("Superscripts and Subscripts")));
220         ranges.push_back(std::make_pair(std::make_pair(0x20A0, 0x20CF), _("Currency Symbols")));
221         ranges.push_back(std::make_pair(std::make_pair(0x20D0, 0x20FF), _("Combining Diacritical Marks for Symbols")));
222         ranges.push_back(std::make_pair(std::make_pair(0x2100, 0x214F), _("Letterlike Symbols")));
223         ranges.push_back(std::make_pair(std::make_pair(0x2150, 0x218F), _("Number Forms")));
224         ranges.push_back(std::make_pair(std::make_pair(0x2190, 0x21FF), _("Arrows")));
225         ranges.push_back(std::make_pair(std::make_pair(0x2200, 0x22FF), _("Mathematical Operators")));
226         ranges.push_back(std::make_pair(std::make_pair(0x2300, 0x23FF), _("Miscellaneous Technical")));
227         ranges.push_back(std::make_pair(std::make_pair(0x2400, 0x243F), _("Control Pictures")));
228         ranges.push_back(std::make_pair(std::make_pair(0x2440, 0x245F), _("Optical Character Recognition")));
229         ranges.push_back(std::make_pair(std::make_pair(0x2460, 0x24FF), _("Enclosed Alphanumerics")));
230         ranges.push_back(std::make_pair(std::make_pair(0x2500, 0x257F), _("Box Drawing")));
231         ranges.push_back(std::make_pair(std::make_pair(0x2580, 0x259F), _("Block Elements")));
232         ranges.push_back(std::make_pair(std::make_pair(0x25A0, 0x25FF), _("Geometric Shapes")));
233         ranges.push_back(std::make_pair(std::make_pair(0x2600, 0x26FF), _("Miscellaneous Symbols")));
234         ranges.push_back(std::make_pair(std::make_pair(0x2700, 0x27BF), _("Dingbats")));
235         ranges.push_back(std::make_pair(std::make_pair(0x27C0, 0x27EF), _("Miscellaneous Mathematical Symbols-A")));
236         ranges.push_back(std::make_pair(std::make_pair(0x27F0, 0x27FF), _("Supplemental Arrows-A")));
237         ranges.push_back(std::make_pair(std::make_pair(0x2800, 0x28FF), _("Braille Patterns")));
238         ranges.push_back(std::make_pair(std::make_pair(0x2900, 0x297F), _("Supplemental Arrows-B")));
239         ranges.push_back(std::make_pair(std::make_pair(0x2980, 0x29FF), _("Miscellaneous Mathematical Symbols-B")));
240         ranges.push_back(std::make_pair(std::make_pair(0x2A00, 0x2AFF), _("Supplemental Mathematical Operators")));
241         ranges.push_back(std::make_pair(std::make_pair(0x2B00, 0x2BFF), _("Miscellaneous Symbols and Arrows")));
242         ranges.push_back(std::make_pair(std::make_pair(0x2C00, 0x2C5F), _("Glagolitic")));
243         ranges.push_back(std::make_pair(std::make_pair(0x2C60, 0x2C7F), _("Latin Extended-C")));
244         ranges.push_back(std::make_pair(std::make_pair(0x2C80, 0x2CFF), _("Coptic")));
245         ranges.push_back(std::make_pair(std::make_pair(0x2D00, 0x2D2F), _("Georgian Supplement")));
246         ranges.push_back(std::make_pair(std::make_pair(0x2D30, 0x2D7F), _("Tifinagh")));
247         ranges.push_back(std::make_pair(std::make_pair(0x2D80, 0x2DDF), _("Ethiopic Extended")));
248         ranges.push_back(std::make_pair(std::make_pair(0x2DE0, 0x2DFF), _("Cyrillic Extended-A")));
249         ranges.push_back(std::make_pair(std::make_pair(0x2E00, 0x2E7F), _("Supplemental Punctuation")));
250         ranges.push_back(std::make_pair(std::make_pair(0x2E80, 0x2EFF), _("CJK Radicals Supplement")));
251         ranges.push_back(std::make_pair(std::make_pair(0x2F00, 0x2FDF), _("Kangxi Radicals")));
252         ranges.push_back(std::make_pair(std::make_pair(0x2FF0, 0x2FFF), _("Ideographic Description Characters")));
253         ranges.push_back(std::make_pair(std::make_pair(0x3000, 0x303F), _("CJK Symbols and Punctuation")));
254         ranges.push_back(std::make_pair(std::make_pair(0x3040, 0x309F), _("Hiragana")));
255         ranges.push_back(std::make_pair(std::make_pair(0x30A0, 0x30FF), _("Katakana")));
256         ranges.push_back(std::make_pair(std::make_pair(0x3100, 0x312F), _("Bopomofo")));
257         ranges.push_back(std::make_pair(std::make_pair(0x3130, 0x318F), _("Hangul Compatibility Jamo")));
258         ranges.push_back(std::make_pair(std::make_pair(0x3190, 0x319F), _("Kanbun")));
259         ranges.push_back(std::make_pair(std::make_pair(0x31A0, 0x31BF), _("Bopomofo Extended")));
260         ranges.push_back(std::make_pair(std::make_pair(0x31C0, 0x31EF), _("CJK Strokes")));
261         ranges.push_back(std::make_pair(std::make_pair(0x31F0, 0x31FF), _("Katakana Phonetic Extensions")));
262         ranges.push_back(std::make_pair(std::make_pair(0x3200, 0x32FF), _("Enclosed CJK Letters and Months")));
263         ranges.push_back(std::make_pair(std::make_pair(0x3300, 0x33FF), _("CJK Compatibility")));
264         ranges.push_back(std::make_pair(std::make_pair(0x3400, 0x4DBF), _("CJK Unified Ideographs Extension A")));
265         ranges.push_back(std::make_pair(std::make_pair(0x4DC0, 0x4DFF), _("Yijing Hexagram Symbols")));
266         ranges.push_back(std::make_pair(std::make_pair(0x4E00, 0x9FFF), _("CJK Unified Ideographs")));
267         ranges.push_back(std::make_pair(std::make_pair(0xA000, 0xA48F), _("Yi Syllables")));
268         ranges.push_back(std::make_pair(std::make_pair(0xA490, 0xA4CF), _("Yi Radicals")));
269         ranges.push_back(std::make_pair(std::make_pair(0xA4D0, 0xA4FF), _("Lisu")));
270         ranges.push_back(std::make_pair(std::make_pair(0xA500, 0xA63F), _("Vai")));
271         ranges.push_back(std::make_pair(std::make_pair(0xA640, 0xA69F), _("Cyrillic Extended-B")));
272         ranges.push_back(std::make_pair(std::make_pair(0xA6A0, 0xA6FF), _("Bamum")));
273         ranges.push_back(std::make_pair(std::make_pair(0xA700, 0xA71F), _("Modifier Tone Letters")));
274         ranges.push_back(std::make_pair(std::make_pair(0xA720, 0xA7FF), _("Latin Extended-D")));
275         ranges.push_back(std::make_pair(std::make_pair(0xA800, 0xA82F), _("Syloti Nagri")));
276         ranges.push_back(std::make_pair(std::make_pair(0xA830, 0xA83F), _("Common Indic Number Forms")));
277         ranges.push_back(std::make_pair(std::make_pair(0xA840, 0xA87F), _("Phags-pa")));
278         ranges.push_back(std::make_pair(std::make_pair(0xA880, 0xA8DF), _("Saurashtra")));
279         ranges.push_back(std::make_pair(std::make_pair(0xA8E0, 0xA8FF), _("Devanagari Extended")));
280         ranges.push_back(std::make_pair(std::make_pair(0xA900, 0xA92F), _("Kayah Li")));
281         ranges.push_back(std::make_pair(std::make_pair(0xA930, 0xA95F), _("Rejang")));
282         ranges.push_back(std::make_pair(std::make_pair(0xA960, 0xA97F), _("Hangul Jamo Extended-A")));
283         ranges.push_back(std::make_pair(std::make_pair(0xA980, 0xA9DF), _("Javanese")));
284         ranges.push_back(std::make_pair(std::make_pair(0xAA00, 0xAA5F), _("Cham")));
285         ranges.push_back(std::make_pair(std::make_pair(0xAA60, 0xAA7F), _("Myanmar Extended-A")));
286         ranges.push_back(std::make_pair(std::make_pair(0xAA80, 0xAADF), _("Tai Viet")));
287         ranges.push_back(std::make_pair(std::make_pair(0xABC0, 0xABFF), _("Meetei Mayek")));
288         ranges.push_back(std::make_pair(std::make_pair(0xAC00, 0xD7AF), _("Hangul Syllables")));
289         ranges.push_back(std::make_pair(std::make_pair(0xD7B0, 0xD7FF), _("Hangul Jamo Extended-B")));
290         ranges.push_back(std::make_pair(std::make_pair(0xD800, 0xDB7F), _("High Surrogates")));
291         ranges.push_back(std::make_pair(std::make_pair(0xDB80, 0xDBFF), _("High Private Use Surrogates")));
292         ranges.push_back(std::make_pair(std::make_pair(0xDC00, 0xDFFF), _("Low Surrogates")));
293         ranges.push_back(std::make_pair(std::make_pair(0xE000, 0xF8FF), _("Private Use Area")));
294         ranges.push_back(std::make_pair(std::make_pair(0xF900, 0xFAFF), _("CJK Compatibility Ideographs")));
295         ranges.push_back(std::make_pair(std::make_pair(0xFB00, 0xFB4F), _("Alphabetic Presentation Forms")));
296         ranges.push_back(std::make_pair(std::make_pair(0xFB50, 0xFDFF), _("Arabic Presentation Forms-A")));
297         ranges.push_back(std::make_pair(std::make_pair(0xFE00, 0xFE0F), _("Variation Selectors")));
298         ranges.push_back(std::make_pair(std::make_pair(0xFE10, 0xFE1F), _("Vertical Forms")));
299         ranges.push_back(std::make_pair(std::make_pair(0xFE20, 0xFE2F), _("Combining Half Marks")));
300         ranges.push_back(std::make_pair(std::make_pair(0xFE30, 0xFE4F), _("CJK Compatibility Forms")));
301         ranges.push_back(std::make_pair(std::make_pair(0xFE50, 0xFE6F), _("Small Form Variants")));
302         ranges.push_back(std::make_pair(std::make_pair(0xFE70, 0xFEFF), _("Arabic Presentation Forms-B")));
303         ranges.push_back(std::make_pair(std::make_pair(0xFF00, 0xFFEF), _("Halfwidth and Fullwidth Forms")));
304         ranges.push_back(std::make_pair(std::make_pair(0xFFF0, 0xFFFF), _("Specials")));
305     }
307     return ranges;
310 class GlyphColumns : public Gtk::TreeModel::ColumnRecord
312 public:
313     Gtk::TreeModelColumn<gunichar> code;
314     Gtk::TreeModelColumn<Glib::ustring> name;
316     GlyphColumns()
317     {
318         add(code);
319         add(name);
320     }
321 };
323 GlyphColumns *GlyphsPanel::getColumns()
325     static GlyphColumns *columns = new GlyphColumns();
327     return columns;
330 /**
331  * Constructor
332  */
333 GlyphsPanel::GlyphsPanel(gchar const *prefsPath) :
334     Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_GLYPHS, "", false),
335     store(Gtk::ListStore::create(*getColumns())),
336     iconView(0),
337     entry(0),
338     label(0),
339     insertBtn(0),
340 #if GLIB_CHECK_VERSION(2,14,0)
341     scriptCombo(0),
342 #endif // GLIB_CHECK_VERSION(2,14,0)
343     fsel(0),
344     targetDesktop(0),
345     deskTrack(),
346     instanceConns(),
347     desktopConns()
349     Gtk::Table *table = new Gtk::Table(3, 1, false);
350     _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET);
351     guint row = 0;
353 // -------------------------------
355     GtkWidget *fontsel = sp_font_selector_new();
356     fsel = SP_FONT_SELECTOR(fontsel);
357     sp_font_selector_set_font(fsel, sp_font_selector_get_font(fsel), 12.0);
359     g_signal_connect( G_OBJECT(fontsel), "font_set", G_CALLBACK(fontChangeCB), this );
361     table->attach(*Gtk::manage(Glib::wrap(fontsel)),
362                   0, 3, row, row + 1,
363                   Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL);
364     row++;
367 // -------------------------------
369 #if GLIB_CHECK_VERSION(2,14,0)
370     {
371         Gtk::Label *label = new Gtk::Label(_("Script: "));
372         table->attach( *Gtk::manage(label),
373                        0, 1, row, row + 1,
374                        Gtk::SHRINK, Gtk::SHRINK);
376         scriptCombo = new Gtk::ComboBoxText();
377         for (std::map<GUnicodeScript, Glib::ustring>::iterator it = getScriptToName().begin(); it != getScriptToName().end(); ++it)
378         {
379             scriptCombo->append_text(it->second);
380         }
382         scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]);
383         sigc::connection conn = scriptCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild));
384         instanceConns.push_back(conn);
386         Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0);
387         align->add(*Gtk::manage(scriptCombo));
388         table->attach( *Gtk::manage(align),
389                        1, 2, row, row + 1,
390                        Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
391     }
393     row++;
394 #endif // GLIB_CHECK_VERSION(2,14,0)
396 // -------------------------------
398     {
399         Gtk::Label *label = new Gtk::Label(_("Range: "));
400         table->attach( *Gtk::manage(label),
401                        0, 1, row, row + 1,
402                        Gtk::SHRINK, Gtk::SHRINK);
404         rangeCombo = new Gtk::ComboBoxText();
405         for ( std::vector<NamedRange>::iterator it = getRanges().begin(); it != getRanges().end(); ++it ) {
406             rangeCombo->append_text(it->second);
407         }
409         rangeCombo->set_active_text(getRanges()[1].second);
410         sigc::connection conn = rangeCombo->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::rebuild));
411         instanceConns.push_back(conn);
413         Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP, 0.0, 0.0);
414         align->add(*Gtk::manage(rangeCombo));
415         table->attach( *Gtk::manage(align),
416                        1, 2, row, row + 1,
417                        Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
418     }
420     row++;
422 // -------------------------------
424     GlyphColumns *columns = getColumns();
426     iconView = new Gtk::IconView(store);
427     iconView->set_text_column(columns->name);
428     //iconView->set_columns(16);
430     sigc::connection conn;
431     conn = iconView->signal_item_activated().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphActivated));
432     instanceConns.push_back(conn);
433     conn = iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::glyphSelectionChanged));
434     instanceConns.push_back(conn);
437     Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow();
438     scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
439     scroller->add(*Gtk::manage(iconView));
440     table->attach(*Gtk::manage(scroller),
441                   0, 3, row, row + 1,
442                   Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL);
443     row++;
445 // -------------------------------
447     Gtk::HBox *box = new Gtk::HBox();
449     entry = new Gtk::Entry();
450     conn = entry->signal_changed().connect(sigc::mem_fun(*this, &GlyphsPanel::calcCanInsert));
451     instanceConns.push_back(conn);
452     entry->set_width_chars(18);
453     box->pack_start(*Gtk::manage(entry), Gtk::PACK_SHRINK);
455     Gtk::Label *pad = new Gtk::Label("    ");
456     box->pack_start(*Gtk::manage(pad), Gtk::PACK_SHRINK);
458     label = new Gtk::Label("      ");
459     box->pack_start(*Gtk::manage(label), Gtk::PACK_SHRINK);
461     pad = new Gtk::Label("");
462     box->pack_start(*Gtk::manage(pad), Gtk::PACK_EXPAND_WIDGET);
464     insertBtn = new Gtk::Button(_("Append"));
465     conn = insertBtn->signal_clicked().connect(sigc::mem_fun(*this, &GlyphsPanel::insertText));
466     instanceConns.push_back(conn);
467 #if GTK_CHECK_VERSION(2,18,0)
468     //gtkmm 2.18
469     insertBtn->set_can_default();
470 #endif
471     insertBtn->set_sensitive(false);
473     box->pack_end(*Gtk::manage(insertBtn), Gtk::PACK_SHRINK);
475     table->attach( *Gtk::manage(box),
476                    0, 3, row, row + 1,
477                    Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
478     row++;
480 // -------------------------------
483     show_all_children();
485     restorePanelPrefs();
487     // Connect this up last
488     conn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &GlyphsPanel::setTargetDesktop) );
489     instanceConns.push_back(conn);
490     deskTrack.connect(GTK_WIDGET(gobj()));
493 GlyphsPanel::~GlyphsPanel()
495     for (std::vector<sigc::connection>::iterator it =  instanceConns.begin(); it != instanceConns.end(); ++it) {
496         it->disconnect();
497     }
498     instanceConns.clear();
499     for (std::vector<sigc::connection>::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) {
500         it->disconnect();
501     }
502     desktopConns.clear();
506 void GlyphsPanel::setDesktop(SPDesktop *desktop)
508     Panel::setDesktop(desktop);
509     deskTrack.setBase(desktop);
512 void GlyphsPanel::setTargetDesktop(SPDesktop *desktop)
514     if (targetDesktop != desktop) {
515         if (targetDesktop) {
516             for (std::vector<sigc::connection>::iterator it = desktopConns.begin(); it != desktopConns.end(); ++it) {
517                 it->disconnect();
518             }
519             desktopConns.clear();
520         }
522         targetDesktop = desktop;
524         if (targetDesktop && targetDesktop->selection) {
525             sigc::connection conn = desktop->selection->connectChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, true)));
526             desktopConns.push_back(conn);
528             // Text selection within selected items has changed:
529             conn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::bind(sigc::mem_fun(*this, &GlyphsPanel::readSelection), true, false)));
530             desktopConns.push_back(conn);
532             // Must check flags, so can't call performUpdate() directly.
533             conn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &GlyphsPanel::selectionModifiedCB)));
534             desktopConns.push_back(conn);
536             readSelection(true, true);
537         }
538     }
541 void GlyphsPanel::insertText()
543     SPItem *textItem = 0;
544     for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
545         if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
546             textItem = SP_ITEM(item->data);
547             break;
548         }
549     }
551     if (textItem) {
552         Glib::ustring glyphs;
553         if (entry->get_text_length() > 0) {
554             glyphs = entry->get_text();
555         } else {
556             Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items();
557             if (!itemArray.empty()) {
558                 Gtk::TreeModel::Path const & path = *itemArray.begin();
559                 Gtk::ListStore::iterator row = store->get_iter(path);
560                 gunichar ch = (*row)[getColumns()->code];
561                 glyphs = ch;
562             }
563         }
565         if (!glyphs.empty()) {
566             Glib::ustring combined;
567             gchar *str = sp_te_get_string_multiline(textItem);
568             if (str) {
569                 combined = str;
570                 g_free(str);
571                 str = 0;
572             }
573             combined += glyphs;
574             sp_te_set_repr_text_multiline(textItem, combined.c_str());
575             DocumentUndo::done(targetDesktop->doc(), SP_VERB_CONTEXT_TEXT, _("Append text"));
576         }
577     }
580 void GlyphsPanel::glyphActivated(Gtk::TreeModel::Path const & path)
582     Gtk::ListStore::iterator row = store->get_iter(path);
583     gunichar ch = (*row)[getColumns()->code];
584     Glib::ustring tmp;
585     tmp += ch;
587     int startPos = 0;
588     int endPos = 0;
589     if (entry->get_selection_bounds(startPos, endPos)) {
590         // there was something selected.
591         entry->delete_text(startPos, endPos);
592     }
593     startPos = entry->get_position();
594     entry->insert_text(tmp, -1, startPos);
595     entry->set_position(startPos);
598 void GlyphsPanel::glyphSelectionChanged()
600     Gtk::IconView::ArrayHandle_TreePaths itemArray = iconView->get_selected_items();
601     if (itemArray.empty()) {
602         label->set_text("      ");
603     } else {
604         Gtk::TreeModel::Path const & path = *itemArray.begin();
605         Gtk::ListStore::iterator row = store->get_iter(path);
606         gunichar ch = (*row)[getColumns()->code];
609         Glib::ustring scriptName;
610 #if GLIB_CHECK_VERSION(2,14,0)
611         GUnicodeScript script = g_unichar_get_script(ch);
612         std::map<GUnicodeScript, Glib::ustring> mappings = getScriptToName();
613         if (mappings.find(script) != mappings.end()) {
614             scriptName = mappings[script];
615         }
616 #endif
617         gchar * tmp = g_strdup_printf("U+%04X %s", ch, scriptName.c_str());
618         label->set_text(tmp);
619     }
620     calcCanInsert();
623 void GlyphsPanel::fontChangeCB(SPFontSelector * /*fontsel*/, font_instance * /*font*/, GlyphsPanel *self)
625     if (self) {
626         self->rebuild();
627     }
630 void GlyphsPanel::selectionModifiedCB(guint flags)
632     bool style = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG |
633                              SP_OBJECT_STYLE_MODIFIED_FLAG  )) != 0 );
635     bool content = ((flags & ( SP_OBJECT_CHILD_MODIFIED_FLAG |
636                                SP_TEXT_CONTENT_MODIFIED_FLAG  )) != 0 );
638     readSelection(style, content);
641 void GlyphsPanel::calcCanInsert()
643     int items = 0;
644     for (const GSList *item = targetDesktop->selection->itemList(); item; item = item->next ) {
645         if (SP_IS_TEXT(item->data) || SP_IS_FLOWTEXT(item->data)) {
646             ++items;
647         }
648     }
650     bool enable = (items == 1);
651     if (enable) {
652         enable &= (!iconView->get_selected_items().empty()
653                    || (entry->get_text_length() > 0));
654     }
656     if (enable != insertBtn->is_sensitive()) {
657         insertBtn->set_sensitive(enable);
658     }
661 void GlyphsPanel::readSelection( bool updateStyle, bool /*updateContent*/ )
663     calcCanInsert();
665     if (targetDesktop && updateStyle) {
666         //SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT);
668         //int result_family = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
669         //int result_style = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
670         //int result_numbers = sp_desktop_query_style(targetDesktop, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
672         //sp_style_unref(query);
673     }
677 void GlyphsPanel::rebuild()
679     font_instance *font = fsel ? sp_font_selector_get_font(fsel) : 0;
680     if (font) {
681         //double  sp_font_selector_get_size (SPFontSelector *fsel);
683 #if GLIB_CHECK_VERSION(2,14,0)
684         GUnicodeScript script = G_UNICODE_SCRIPT_INVALID_CODE;
685         Glib::ustring scriptName = scriptCombo->get_active_text();
686         std::map<GUnicodeScript, Glib::ustring> items = getScriptToName();
687         for (std::map<GUnicodeScript, Glib::ustring>::iterator it = items.begin(); it != items.end(); ++it) {
688             if (scriptName == it->second) {
689                 script = it->first;
690                 break;
691             }
692         }
693 #endif // GLIB_CHECK_VERSION(2,14,0)
695         // Disconnect the model while we update it. Simple work-around for 5x+ performance boost.
696         Glib::RefPtr<Gtk::ListStore> tmp = Gtk::ListStore::create(*getColumns());
697         iconView->set_model(tmp);
699         gunichar lower = 0x0001;
700         gunichar upper = 0xFFFD;
701         int active = rangeCombo->get_active_row_number();
702         if (active >= 0) {
703             lower = getRanges()[active].first.first;
704             upper = getRanges()[active].first.second;
705         }
706         std::vector<gunichar> present;
707         for (gunichar ch = lower; ch <= upper; ch++) {
708             int glyphId = font->MapUnicodeChar(ch);
709             if (glyphId > 0) {
710 #if GLIB_CHECK_VERSION(2,14,0)
711                 if ((script == G_UNICODE_SCRIPT_INVALID_CODE) || (script == g_unichar_get_script(ch))) {
712                     present.push_back(ch);
713                 }
714 #else
715                 present.push_back(ch);
716 #endif
717             }
718         }
720         GlyphColumns *columns = getColumns();
721         store->clear();
722         for (std::vector<gunichar>::iterator it = present.begin(); it != present.end(); ++it)
723         {
724             Gtk::ListStore::iterator row = store->append();
725             Glib::ustring tmp;
726             tmp += *it;
727             (*row)[columns->code] = *it;
728             (*row)[columns->name] = tmp;
729         }
731         // Reconnect the model once it has been updated:
732         iconView->set_model(store);
733     }
737 } // namespace Dialogs
738 } // namespace UI
739 } // namespace Inkscape
741 /*
742   Local Variables:
743   mode:c++
744   c-file-style:"stroustrup"
745   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
746   indent-tabs-mode:nil
747   fill-column:99
748   End:
749 */
750 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :