1 /*
2 * Copyright © 2004 Noah Levitt
3 * Copyright © 2007 Christian Persch
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 3 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
18 */
19
20 #include <config.h>
21 #include <glib/gi18n-lib.h>
22
23 #include "gucharmap.h"
24 #include "gucharmap-private.h"
25
26 #include "unicode-blocks.h"
27
28 enum
29 {
30 BLOCK_CHAPTERS_MODEL_ID = 0,
31 BLOCK_CHAPTERS_MODEL_LABEL = GUCHARMAP_CHAPTERS_MODEL_COLUMN_LABEL,
32 BLOCK_CHAPTERS_MODEL_LABEL_ATTRS = _GUCHARMAP_CHAPTERS_MODEL_COLUMN_LABEL_ATTRS,
33 BLOCK_CHAPTERS_MODEL_BLOCK,
34 BLOCK_CHAPTERS_MODEL_UNICODE_BLOCK_PTR,
35 BLOCK_CHAPTERS_MODEL_NUM_COLUMNS
36 };
37
38 static void
sort_column_changed_cb(GtkTreeSortable * sortable,gpointer user_data)39 sort_column_changed_cb (GtkTreeSortable *sortable,
40 gpointer user_data)
41 {
42 GucharmapChaptersModel *model = GUCHARMAP_CHAPTERS_MODEL (sortable);
43
44 if (model->priv->sort_column == BLOCK_CHAPTERS_MODEL_BLOCK)
45 model->priv->sort_column = BLOCK_CHAPTERS_MODEL_LABEL;
46 else
47 model->priv->sort_column = BLOCK_CHAPTERS_MODEL_BLOCK;
48
49 g_signal_handlers_block_by_func(sortable, G_CALLBACK(sort_column_changed_cb), NULL);
50 gtk_tree_sortable_set_sort_column_id (sortable,
51 model->priv->sort_column,
52 GTK_SORT_ASCENDING);
53 g_signal_handlers_unblock_by_func(sortable, G_CALLBACK(sort_column_changed_cb), NULL);
54 }
55
56 static void
gucharmap_block_chapters_model_init(GucharmapBlockChaptersModel * model)57 gucharmap_block_chapters_model_init (GucharmapBlockChaptersModel *model)
58 {
59 GucharmapChaptersModel *chapters_model = GUCHARMAP_CHAPTERS_MODEL (model);
60 GtkListStore *store = GTK_LIST_STORE (model);
61 GtkTreeIter iter;
62 guint i;
63 GType types[] = {
64 G_TYPE_STRING,
65 G_TYPE_STRING,
66 PANGO_TYPE_ATTR_LIST,
67 G_TYPE_STRING,
68 G_TYPE_POINTER
69 };
70 PangoAttrList *attr_list;
71
72 attr_list = pango_attr_list_new ();
73 pango_attr_list_insert (attr_list, pango_attr_style_new (PANGO_STYLE_ITALIC));
74
75 gtk_list_store_set_column_types (store, G_N_ELEMENTS (types), types);
76
77 gtk_list_store_append (store, &iter);
78 gtk_list_store_set (store, &iter,
79 BLOCK_CHAPTERS_MODEL_ID, "All",
80 BLOCK_CHAPTERS_MODEL_LABEL, _("All"),
81 BLOCK_CHAPTERS_MODEL_LABEL_ATTRS, attr_list,
82 BLOCK_CHAPTERS_MODEL_BLOCK, "",
83 BLOCK_CHAPTERS_MODEL_UNICODE_BLOCK_PTR, NULL,
84 -1);
85
86 pango_attr_list_unref (attr_list);
87
88 for (i = 0; i < G_N_ELEMENTS (unicode_blocks); i++)
89 {
90 static gchar block_start[12];
91 const char *block_name;
92
93 g_snprintf (block_start, sizeof (block_start), "%012" G_GUINT32_FORMAT, unicode_blocks[i].start);
94 block_name = unicode_blocks_strings + unicode_blocks[i].block_name_index;
95
96 gtk_list_store_append (store, &iter);
97 gtk_list_store_set (store, &iter,
98 BLOCK_CHAPTERS_MODEL_ID, block_name,
99 BLOCK_CHAPTERS_MODEL_LABEL, _(block_name),
100 BLOCK_CHAPTERS_MODEL_LABEL_ATTRS, NULL,
101 BLOCK_CHAPTERS_MODEL_BLOCK, block_start,
102 BLOCK_CHAPTERS_MODEL_UNICODE_BLOCK_PTR, unicode_blocks + i,
103 -1);
104 }
105
106 g_signal_connect (model, "sort-column-changed", G_CALLBACK (sort_column_changed_cb), NULL);
107
108 /* This will switch to its default BLOCK_CHAPTERS_MODEL_BLOCK when
109 * gucharmap_chapters_view_set_model() calls
110 * gtk_tree_sortable_set_sort_column_id() and triggers
111 * "sort-column-changed". */
112 chapters_model->priv->sort_column = BLOCK_CHAPTERS_MODEL_LABEL;
113 }
114
115 static GucharmapCodepointList *
get_codepoint_list(GucharmapChaptersModel * chapters,GtkTreeIter * iter)116 get_codepoint_list (GucharmapChaptersModel *chapters,
117 GtkTreeIter *iter)
118 {
119 GtkTreeModel *model = GTK_TREE_MODEL (chapters);
120 UnicodeBlock *unicode_block;
121
122 gtk_tree_model_get (model, iter, BLOCK_CHAPTERS_MODEL_UNICODE_BLOCK_PTR, &unicode_block, -1);
123
124 /* special "All" block */
125 if (unicode_block == NULL)
126 return gucharmap_block_codepoint_list_new (0, UNICHAR_MAX);
127
128 return gucharmap_block_codepoint_list_new (unicode_block->start, unicode_block->end);
129 }
130
131 static GucharmapCodepointList *
get_book_codepoint_list(GucharmapChaptersModel * model)132 get_book_codepoint_list (GucharmapChaptersModel *model)
133 {
134 GucharmapChaptersModelPrivate *model_priv = model->priv;
135
136 if (model_priv->book_list == NULL) {
137 model_priv->book_list = gucharmap_block_codepoint_list_new (0, UNICHAR_MAX);
138 }
139
140 return g_object_ref (model_priv->book_list);
141 }
142
143 /* XXX linear search */
144 static gboolean
character_to_iter(GucharmapChaptersModel * chapters,gunichar wc,GtkTreeIter * _iter)145 character_to_iter (GucharmapChaptersModel *chapters,
146 gunichar wc,
147 GtkTreeIter *_iter)
148 {
149 GtkTreeModel *model = GTK_TREE_MODEL (chapters);
150 GtkTreeIter iter, all_iter;
151 gboolean all_iter_set = TRUE;
152
153 if (wc > UNICHAR_MAX)
154 return FALSE;
155
156 if (!gtk_tree_model_get_iter_first (model, &iter))
157 return FALSE;
158
159 do
160 {
161 UnicodeBlock *unicode_block;
162
163 gtk_tree_model_get (model, &iter, BLOCK_CHAPTERS_MODEL_UNICODE_BLOCK_PTR, &unicode_block, -1);
164
165 /* skip "All" block */
166 if (unicode_block == NULL)
167 {
168 all_iter = iter;
169 all_iter_set = TRUE;
170 continue;
171 }
172
173 if (wc >= unicode_block->start && wc <= unicode_block->end)
174 {
175 *_iter = iter;
176 return TRUE;
177 }
178 }
179 while (gtk_tree_model_iter_next (model, &iter));
180
181 /* "All" is the last resort */
182 g_assert (all_iter_set);
183 *_iter = all_iter;
184 return TRUE;
185 }
186
187 static void
gucharmap_block_chapters_model_class_init(GucharmapBlockChaptersModelClass * clazz)188 gucharmap_block_chapters_model_class_init (GucharmapBlockChaptersModelClass *clazz)
189 {
190 GucharmapChaptersModelClass *chapters_class = GUCHARMAP_CHAPTERS_MODEL_CLASS (clazz);
191
192 _gucharmap_intl_ensure_initialized ();
193
194 chapters_class->title = _("Unicode Block");
195 chapters_class->character_to_iter = character_to_iter;
196 chapters_class->get_codepoint_list = get_codepoint_list;
197 chapters_class->get_book_codepoint_list = get_book_codepoint_list;
198 }
199
G_DEFINE_TYPE(GucharmapBlockChaptersModel,gucharmap_block_chapters_model,GUCHARMAP_TYPE_CHAPTERS_MODEL)200 G_DEFINE_TYPE (GucharmapBlockChaptersModel, gucharmap_block_chapters_model, GUCHARMAP_TYPE_CHAPTERS_MODEL)
201
202 GucharmapChaptersModel *
203 gucharmap_block_chapters_model_new (void)
204 {
205 return g_object_new (gucharmap_block_chapters_model_get_type (), NULL);
206 }
207