File: | ctk/ctkrecentchooserutils.c |
Warning: | line 327, column 27 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* ctkrecentchooserutils.h - Private utility functions for implementing a |
2 | * CtkRecentChooser interface |
3 | * |
4 | * Copyright (C) 2006 Emmanuele Bassi |
5 | * |
6 | * All rights reserved |
7 | * |
8 | * This library is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Library General Public |
10 | * License as published by the Free Software Foundation; either |
11 | * version 2 of the License, or (at your option) any later version. |
12 | * |
13 | * This library is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Library General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Library General Public |
19 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
20 | * |
21 | * Based on ctkfilechooserutils.c: |
22 | * Copyright (C) 2003 Red Hat, Inc. |
23 | */ |
24 | |
25 | #include "config.h" |
26 | |
27 | #include "ctkrecentchooserutils.h" |
28 | |
29 | /* Methods */ |
30 | static void delegate_set_sort_func (CtkRecentChooser *chooser, |
31 | CtkRecentSortFunc sort_func, |
32 | gpointer sort_data, |
33 | GDestroyNotify data_destroy); |
34 | static void delegate_add_filter (CtkRecentChooser *chooser, |
35 | CtkRecentFilter *filter); |
36 | static void delegate_remove_filter (CtkRecentChooser *chooser, |
37 | CtkRecentFilter *filter); |
38 | static GSList *delegate_list_filters (CtkRecentChooser *chooser); |
39 | static gboolean delegate_select_uri (CtkRecentChooser *chooser, |
40 | const gchar *uri, |
41 | GError **error); |
42 | static void delegate_unselect_uri (CtkRecentChooser *chooser, |
43 | const gchar *uri); |
44 | static GList *delegate_get_items (CtkRecentChooser *chooser); |
45 | static CtkRecentManager *delegate_get_recent_manager (CtkRecentChooser *chooser); |
46 | static void delegate_select_all (CtkRecentChooser *chooser); |
47 | static void delegate_unselect_all (CtkRecentChooser *chooser); |
48 | static gboolean delegate_set_current_uri (CtkRecentChooser *chooser, |
49 | const gchar *uri, |
50 | GError **error); |
51 | static gchar * delegate_get_current_uri (CtkRecentChooser *chooser); |
52 | |
53 | /* Signals */ |
54 | static void delegate_notify (GObject *object, |
55 | GParamSpec *pspec, |
56 | gpointer user_data); |
57 | static void delegate_selection_changed (CtkRecentChooser *receiver, |
58 | gpointer user_data); |
59 | static void delegate_item_activated (CtkRecentChooser *receiver, |
60 | gpointer user_data); |
61 | |
62 | /** |
63 | * _ctk_recent_chooser_install_properties: |
64 | * @klass: the class structure for a type deriving from #GObject |
65 | * |
66 | * Installs the necessary properties for a class implementing |
67 | * #CtkRecentChooser. A #CtkParamSpecOverride property is installed |
68 | * for each property, using the values from the #CtkRecentChooserProp |
69 | * enumeration. The caller must make sure itself that the enumeration |
70 | * values don’t collide with some other property values they |
71 | * are using. |
72 | */ |
73 | void |
74 | _ctk_recent_chooser_install_properties (GObjectClass *klass) |
75 | { |
76 | g_object_class_override_property (klass, |
77 | CTK_RECENT_CHOOSER_PROP_RECENT_MANAGER, |
78 | "recent-manager"); |
79 | g_object_class_override_property (klass, |
80 | CTK_RECENT_CHOOSER_PROP_SHOW_PRIVATE, |
81 | "show-private"); |
82 | g_object_class_override_property (klass, |
83 | CTK_RECENT_CHOOSER_PROP_SHOW_TIPS, |
84 | "show-tips"); |
85 | g_object_class_override_property (klass, |
86 | CTK_RECENT_CHOOSER_PROP_SHOW_ICONS, |
87 | "show-icons"); |
88 | g_object_class_override_property (klass, |
89 | CTK_RECENT_CHOOSER_PROP_SHOW_NOT_FOUND, |
90 | "show-not-found"); |
91 | g_object_class_override_property (klass, |
92 | CTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE, |
93 | "select-multiple"); |
94 | g_object_class_override_property (klass, |
95 | CTK_RECENT_CHOOSER_PROP_LIMIT, |
96 | "limit"); |
97 | g_object_class_override_property (klass, |
98 | CTK_RECENT_CHOOSER_PROP_LOCAL_ONLY, |
99 | "local-only"); |
100 | g_object_class_override_property (klass, |
101 | CTK_RECENT_CHOOSER_PROP_SORT_TYPE, |
102 | "sort-type"); |
103 | g_object_class_override_property (klass, |
104 | CTK_RECENT_CHOOSER_PROP_FILTER, |
105 | "filter"); |
106 | } |
107 | |
108 | /** |
109 | * _ctk_recent_chooser_delegate_iface_init: |
110 | * @iface: a #CtkRecentChooserIface |
111 | * |
112 | * An interface-initialization function for use in cases where |
113 | * an object is simply delegating the methods, signals of |
114 | * the #CtkRecentChooser interface to another object. |
115 | * _ctk_recent_chooser_set_delegate() must be called on each |
116 | * instance of the object so that the delegate object can |
117 | * be found. |
118 | */ |
119 | void |
120 | _ctk_recent_chooser_delegate_iface_init (CtkRecentChooserIface *iface) |
121 | { |
122 | iface->set_current_uri = delegate_set_current_uri; |
123 | iface->get_current_uri = delegate_get_current_uri; |
124 | iface->select_uri = delegate_select_uri; |
125 | iface->unselect_uri = delegate_unselect_uri; |
126 | iface->select_all = delegate_select_all; |
127 | iface->unselect_all = delegate_unselect_all; |
128 | iface->get_items = delegate_get_items; |
129 | iface->get_recent_manager = delegate_get_recent_manager; |
130 | iface->set_sort_func = delegate_set_sort_func; |
131 | iface->add_filter = delegate_add_filter; |
132 | iface->remove_filter = delegate_remove_filter; |
133 | iface->list_filters = delegate_list_filters; |
134 | } |
135 | |
136 | /** |
137 | * _ctk_recent_chooser_set_delegate: |
138 | * @receiver: a #GObject implementing #CtkRecentChooser |
139 | * @delegate: another #GObject implementing #CtkRecentChooser |
140 | * |
141 | * Establishes that calls on @receiver for #CtkRecentChooser |
142 | * methods should be delegated to @delegate, and that |
143 | * #CtkRecentChooser signals emitted on @delegate should be |
144 | * forwarded to @receiver. Must be used in conjunction with |
145 | * _ctk_recent_chooser_delegate_iface_init(). |
146 | */ |
147 | void |
148 | _ctk_recent_chooser_set_delegate (CtkRecentChooser *receiver, |
149 | CtkRecentChooser *delegate) |
150 | { |
151 | g_return_if_fail (CTK_IS_RECENT_CHOOSER (receiver))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((receiver)); GType __t = ((ctk_recent_chooser_get_type () )); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_RECENT_CHOOSER (receiver)"); return ; } } while (0); |
152 | g_return_if_fail (CTK_IS_RECENT_CHOOSER (delegate))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((delegate)); GType __t = ((ctk_recent_chooser_get_type () )); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_RECENT_CHOOSER (delegate)"); return ; } } while (0); |
153 | |
154 | g_object_set_data (G_OBJECT (receiver)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((receiver)), (((GType) ((20) << (2)))))))), |
155 | "ctk-recent-chooser-delegate", delegate); |
156 | |
157 | g_signal_connect (delegate, "notify",g_signal_connect_data ((delegate), ("notify"), (((GCallback) ( delegate_notify))), (receiver), ((void*)0), (GConnectFlags) 0 ) |
158 | G_CALLBACK (delegate_notify), receiver)g_signal_connect_data ((delegate), ("notify"), (((GCallback) ( delegate_notify))), (receiver), ((void*)0), (GConnectFlags) 0 ); |
159 | g_signal_connect (delegate, "selection-changed",g_signal_connect_data ((delegate), ("selection-changed"), ((( GCallback) (delegate_selection_changed))), (receiver), ((void *)0), (GConnectFlags) 0) |
160 | G_CALLBACK (delegate_selection_changed), receiver)g_signal_connect_data ((delegate), ("selection-changed"), ((( GCallback) (delegate_selection_changed))), (receiver), ((void *)0), (GConnectFlags) 0); |
161 | g_signal_connect (delegate, "item-activated",g_signal_connect_data ((delegate), ("item-activated"), (((GCallback ) (delegate_item_activated))), (receiver), ((void*)0), (GConnectFlags ) 0) |
162 | G_CALLBACK (delegate_item_activated), receiver)g_signal_connect_data ((delegate), ("item-activated"), (((GCallback ) (delegate_item_activated))), (receiver), ((void*)0), (GConnectFlags ) 0); |
163 | } |
164 | |
165 | GQuark |
166 | _ctk_recent_chooser_delegate_get_quark (void) |
167 | { |
168 | static GQuark quark = 0; |
169 | |
170 | if (G_UNLIKELY (quark == 0)(quark == 0)) |
171 | quark = g_quark_from_static_string ("ctk-recent-chooser-delegate"); |
172 | |
173 | return quark; |
174 | } |
175 | |
176 | static CtkRecentChooser * |
177 | get_delegate (CtkRecentChooser *receiver) |
178 | { |
179 | return g_object_get_qdata (G_OBJECT (receiver)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((receiver)), (((GType) ((20) << (2)))))))), |
180 | CTK_RECENT_CHOOSER_DELEGATE_QUARK(_ctk_recent_chooser_delegate_get_quark ())); |
181 | } |
182 | |
183 | static void |
184 | delegate_set_sort_func (CtkRecentChooser *chooser, |
185 | CtkRecentSortFunc sort_func, |
186 | gpointer sort_data, |
187 | GDestroyNotify data_destroy) |
188 | { |
189 | ctk_recent_chooser_set_sort_func (get_delegate (chooser), |
190 | sort_func, |
191 | sort_data, |
192 | data_destroy); |
193 | } |
194 | |
195 | static void |
196 | delegate_add_filter (CtkRecentChooser *chooser, |
197 | CtkRecentFilter *filter) |
198 | { |
199 | ctk_recent_chooser_add_filter (get_delegate (chooser), filter); |
200 | } |
201 | |
202 | static void |
203 | delegate_remove_filter (CtkRecentChooser *chooser, |
204 | CtkRecentFilter *filter) |
205 | { |
206 | ctk_recent_chooser_remove_filter (get_delegate (chooser), filter); |
207 | } |
208 | |
209 | static GSList * |
210 | delegate_list_filters (CtkRecentChooser *chooser) |
211 | { |
212 | return ctk_recent_chooser_list_filters (get_delegate (chooser)); |
213 | } |
214 | |
215 | static gboolean |
216 | delegate_select_uri (CtkRecentChooser *chooser, |
217 | const gchar *uri, |
218 | GError **error) |
219 | { |
220 | return ctk_recent_chooser_select_uri (get_delegate (chooser), uri, error); |
221 | } |
222 | |
223 | static void |
224 | delegate_unselect_uri (CtkRecentChooser *chooser, |
225 | const gchar *uri) |
226 | { |
227 | ctk_recent_chooser_unselect_uri (get_delegate (chooser), uri); |
228 | } |
229 | |
230 | static GList * |
231 | delegate_get_items (CtkRecentChooser *chooser) |
232 | { |
233 | return ctk_recent_chooser_get_items (get_delegate (chooser)); |
234 | } |
235 | |
236 | static CtkRecentManager * |
237 | delegate_get_recent_manager (CtkRecentChooser *chooser) |
238 | { |
239 | return _ctk_recent_chooser_get_recent_manager (get_delegate (chooser)); |
240 | } |
241 | |
242 | static void |
243 | delegate_select_all (CtkRecentChooser *chooser) |
244 | { |
245 | ctk_recent_chooser_select_all (get_delegate (chooser)); |
246 | } |
247 | |
248 | static void |
249 | delegate_unselect_all (CtkRecentChooser *chooser) |
250 | { |
251 | ctk_recent_chooser_unselect_all (get_delegate (chooser)); |
252 | } |
253 | |
254 | static gboolean |
255 | delegate_set_current_uri (CtkRecentChooser *chooser, |
256 | const gchar *uri, |
257 | GError **error) |
258 | { |
259 | return ctk_recent_chooser_set_current_uri (get_delegate (chooser), uri, error); |
260 | } |
261 | |
262 | static gchar * |
263 | delegate_get_current_uri (CtkRecentChooser *chooser) |
264 | { |
265 | return ctk_recent_chooser_get_current_uri (get_delegate (chooser)); |
266 | } |
267 | |
268 | static void |
269 | delegate_notify (GObject *object, |
270 | GParamSpec *pspec, |
271 | gpointer user_data) |
272 | { |
273 | gpointer iface; |
274 | |
275 | iface = g_type_interface_peek (g_type_class_peek (G_OBJECT_TYPE (object)(((((GTypeClass*) (((GTypeInstance*) (object))->g_class))-> g_type)))), |
276 | ctk_recent_chooser_get_type ()); |
277 | if (g_object_interface_find_property (iface, pspec->name)) |
278 | g_object_notify (user_data, pspec->name); |
279 | } |
280 | |
281 | static void |
282 | delegate_selection_changed (CtkRecentChooser *receiver G_GNUC_UNUSED__attribute__ ((__unused__)), |
283 | gpointer user_data) |
284 | { |
285 | _ctk_recent_chooser_selection_changed (CTK_RECENT_CHOOSER (user_data)((((CtkRecentChooser*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((user_data)), ((ctk_recent_chooser_get_type ( )))))))); |
286 | } |
287 | |
288 | static void |
289 | delegate_item_activated (CtkRecentChooser *receiver G_GNUC_UNUSED__attribute__ ((__unused__)), |
290 | gpointer user_data) |
291 | { |
292 | _ctk_recent_chooser_item_activated (CTK_RECENT_CHOOSER (user_data)((((CtkRecentChooser*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((user_data)), ((ctk_recent_chooser_get_type ( )))))))); |
293 | } |
294 | |
295 | static gint |
296 | sort_recent_items_mru (CtkRecentInfo *a, |
297 | CtkRecentInfo *b, |
298 | gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__))) |
299 | { |
300 | g_assert (a != NULL && b != NULL)do { if (a != ((void*)0) && b != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkrecentchooserutils.c", 300, ((const char*) (__func__ )), "a != NULL && b != NULL"); } while (0); |
301 | |
302 | return g_date_time_to_unix (ctk_recent_info_get_modified (b)) - g_date_time_to_unix (ctk_recent_info_get_modified (a)); |
303 | } |
304 | |
305 | static gint |
306 | sort_recent_items_lru (CtkRecentInfo *a, |
307 | CtkRecentInfo *b, |
308 | gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__))) |
309 | { |
310 | g_assert (a != NULL && b != NULL)do { if (a != ((void*)0) && b != ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkrecentchooserutils.c", 310, ((const char*) (__func__ )), "a != NULL && b != NULL"); } while (0); |
311 | |
312 | return -1 * (g_date_time_to_unix (ctk_recent_info_get_modified (b)) - g_date_time_to_unix (ctk_recent_info_get_modified (a))); |
313 | } |
314 | |
315 | typedef struct |
316 | { |
317 | CtkRecentSortFunc func; |
318 | gpointer data; |
319 | } SortRecentData; |
320 | |
321 | /* our proxy sorting function */ |
322 | static gint |
323 | sort_recent_items_proxy (gpointer *a, |
324 | gpointer *b, |
325 | gpointer user_data) |
326 | { |
327 | CtkRecentInfo *info_a = (CtkRecentInfo *) a; |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
328 | CtkRecentInfo *info_b = (CtkRecentInfo *) b; |
329 | SortRecentData *sort_recent = user_data; |
330 | |
331 | if (sort_recent->func) |
332 | return (* sort_recent->func) (info_a, info_b, sort_recent->data); |
333 | |
334 | /* fallback */ |
335 | return 0; |
336 | } |
337 | |
338 | static gboolean |
339 | get_is_recent_filtered (CtkRecentFilter *filter, |
340 | CtkRecentInfo *info) |
341 | { |
342 | CtkRecentFilterInfo filter_info; |
343 | CtkRecentFilterFlags needed; |
344 | gboolean retval; |
345 | |
346 | g_assert (info != NULL)do { if (info != ((void*)0)) ; else g_assertion_message_expr ( "Ctk", "ctkrecentchooserutils.c", 346, ((const char*) (__func__ )), "info != NULL"); } while (0); |
347 | |
348 | needed = ctk_recent_filter_get_needed (filter); |
349 | |
350 | filter_info.contains = CTK_RECENT_FILTER_URI | CTK_RECENT_FILTER_MIME_TYPE; |
351 | |
352 | filter_info.uri = ctk_recent_info_get_uri (info); |
353 | filter_info.mime_type = ctk_recent_info_get_mime_type (info); |
354 | |
355 | if (needed & CTK_RECENT_FILTER_DISPLAY_NAME) |
356 | { |
357 | filter_info.display_name = ctk_recent_info_get_display_name (info); |
358 | filter_info.contains |= CTK_RECENT_FILTER_DISPLAY_NAME; |
359 | } |
360 | else |
361 | filter_info.uri = NULL((void*)0); |
362 | |
363 | if (needed & CTK_RECENT_FILTER_APPLICATION) |
364 | { |
365 | filter_info.applications = (const gchar **) ctk_recent_info_get_applications (info, NULL((void*)0)); |
366 | filter_info.contains |= CTK_RECENT_FILTER_APPLICATION; |
367 | } |
368 | else |
369 | filter_info.applications = NULL((void*)0); |
370 | |
371 | if (needed & CTK_RECENT_FILTER_GROUP) |
372 | { |
373 | filter_info.groups = (const gchar **) ctk_recent_info_get_groups (info, NULL((void*)0)); |
374 | filter_info.contains |= CTK_RECENT_FILTER_GROUP; |
375 | } |
376 | else |
377 | filter_info.groups = NULL((void*)0); |
378 | |
379 | if (needed & CTK_RECENT_FILTER_AGE) |
380 | { |
381 | filter_info.age = ctk_recent_info_get_age (info); |
382 | filter_info.contains |= CTK_RECENT_FILTER_AGE; |
383 | } |
384 | else |
385 | filter_info.age = -1; |
386 | |
387 | retval = ctk_recent_filter_filter (filter, &filter_info); |
388 | |
389 | /* these we own */ |
390 | if (filter_info.applications) |
391 | g_strfreev ((gchar **) filter_info.applications); |
392 | if (filter_info.groups) |
393 | g_strfreev ((gchar **) filter_info.groups); |
394 | |
395 | return !retval; |
396 | } |
397 | |
398 | /* |
399 | * _ctk_recent_chooser_get_items: |
400 | * @chooser: a #CtkRecentChooser |
401 | * @filter: a #CtkRecentFilter |
402 | * @sort_func: (allow-none): sorting function, or %NULL |
403 | * @sort_data: (allow-none): sorting function data, or %NULL |
404 | * |
405 | * Default implementation for getting the filtered, sorted and |
406 | * clamped list of recently used resources from a #CtkRecentChooser. |
407 | * This function should be used by implementations of the |
408 | * #CtkRecentChooser interface inside the CtkRecentChooser::get_items |
409 | * vfunc. |
410 | * |
411 | * Returns: a list of #CtkRecentInfo objects |
412 | */ |
413 | GList * |
414 | _ctk_recent_chooser_get_items (CtkRecentChooser *chooser, |
415 | CtkRecentFilter *filter, |
416 | CtkRecentSortFunc sort_func, |
417 | gpointer sort_data) |
418 | { |
419 | CtkRecentManager *manager; |
420 | gint limit; |
421 | CtkRecentSortType sort_type; |
422 | GList *items; |
423 | GCompareDataFunc compare_func; |
424 | gint length; |
425 | |
426 | g_return_val_if_fail (CTK_IS_RECENT_CHOOSER (chooser), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((chooser)); GType __t = ((ctk_recent_chooser_get_type ()) ); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_RECENT_CHOOSER (chooser)"); return (((void*)0)); } } while (0); |
427 | |
428 | manager = _ctk_recent_chooser_get_recent_manager (chooser); |
429 | if (!manager) |
430 | return NULL((void*)0); |
431 | |
432 | items = ctk_recent_manager_get_items (manager); |
433 | if (!items) |
434 | return NULL((void*)0); |
435 | |
436 | limit = ctk_recent_chooser_get_limit (chooser); |
437 | if (limit == 0) |
438 | return NULL((void*)0); |
439 | |
440 | if (filter) |
441 | { |
442 | GList *filter_items, *l; |
443 | gboolean local_only = FALSE(0); |
444 | gboolean show_private = FALSE(0); |
445 | gboolean show_not_found = FALSE(0); |
446 | |
447 | g_object_get (G_OBJECT (chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((chooser)), (((GType) ((20) << (2)))))))), |
448 | "local-only", &local_only, |
449 | "show-private", &show_private, |
450 | "show-not-found", &show_not_found, |
451 | NULL((void*)0)); |
452 | |
453 | filter_items = NULL((void*)0); |
454 | for (l = items; l != NULL((void*)0); l = l->next) |
455 | { |
456 | CtkRecentInfo *info = l->data; |
457 | gboolean remove_item = FALSE(0); |
458 | |
459 | if (get_is_recent_filtered (filter, info)) |
460 | remove_item = TRUE(!(0)); |
461 | |
462 | if (local_only && !ctk_recent_info_is_local (info)) |
463 | remove_item = TRUE(!(0)); |
464 | |
465 | if (!show_private && ctk_recent_info_get_private_hint (info)) |
466 | remove_item = TRUE(!(0)); |
467 | |
468 | if (!show_not_found && !ctk_recent_info_exists (info)) |
469 | remove_item = TRUE(!(0)); |
470 | |
471 | if (!remove_item) |
472 | filter_items = g_list_prepend (filter_items, info); |
473 | else |
474 | ctk_recent_info_unref (info); |
475 | } |
476 | |
477 | g_list_free (items); |
478 | items = filter_items; |
479 | } |
480 | |
481 | if (!items) |
482 | return NULL((void*)0); |
483 | |
484 | sort_type = ctk_recent_chooser_get_sort_type (chooser); |
485 | switch (sort_type) |
486 | { |
487 | case CTK_RECENT_SORT_NONE: |
488 | compare_func = NULL((void*)0); |
489 | break; |
490 | case CTK_RECENT_SORT_MRU: |
491 | compare_func = (GCompareDataFunc) sort_recent_items_mru; |
492 | break; |
493 | case CTK_RECENT_SORT_LRU: |
494 | compare_func = (GCompareDataFunc) sort_recent_items_lru; |
495 | break; |
496 | case CTK_RECENT_SORT_CUSTOM: |
497 | compare_func = (GCompareDataFunc) sort_recent_items_proxy; |
498 | break; |
499 | default: |
500 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkrecentchooserutils.c" , 500, ((const char*) (__func__)), ((void*)0)); } while (0); |
501 | break; |
502 | } |
503 | |
504 | if (compare_func) |
505 | { |
506 | SortRecentData sort_recent; |
507 | |
508 | sort_recent.func = sort_func; |
509 | sort_recent.data = sort_data; |
510 | |
511 | items = g_list_sort_with_data (items, compare_func, &sort_recent); |
512 | } |
513 | |
514 | length = g_list_length (items); |
515 | if ((limit != -1) && (length > limit)) |
516 | { |
517 | GList *clamp, *l; |
518 | |
519 | clamp = g_list_nth (items, limit - 1); |
520 | if (!clamp) |
521 | return items; |
522 | |
523 | l = clamp->next; |
524 | clamp->next = NULL((void*)0); |
525 | |
526 | g_list_free_full (l, (GDestroyNotify) ctk_recent_info_unref); |
527 | } |
528 | |
529 | return items; |
530 | } |