1 /*
2 * panel-glib.c: various small extensions to glib
3 *
4 * Copyright (C) 2008 Novell, Inc.
5 * Copyright (C) 2012-2021 MATE Developers
6 *
7 * Originally based on code from panel-util.c (there was no relevant copyright
8 * header at the time), but the code was:
9 * Copyright (C) Novell, Inc. (for the panel_g_utf8_strstrcase() code)
10 * Copyright (C) Dennis Cranston (for the panel_g_lookup_in_data_dirs() code)
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301, USA.
26 *
27 * Authors:
28 * Vincent Untz <vuntz@gnome.org>
29 */
30
31 #include <string.h>
32
33 #include <glib.h>
34
35 #include "panel-glib.h"
36
37 typedef char * (*LookupInDir) (const char *basename, const char *dir);
38
39 static char *
_lookup_in_dir(const char * basename,const char * dir)40 _lookup_in_dir (const char *basename,
41 const char *dir)
42 {
43 char *path;
44
45 path = g_build_filename (dir, basename, NULL);
46 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
47 g_free (path);
48 return NULL;
49 }
50
51 return path;
52 }
53
54 static char *
_lookup_in_applications_subdir(const char * basename,const char * dir)55 _lookup_in_applications_subdir (const char *basename,
56 const char *dir)
57 {
58 char *path;
59
60 path = g_build_filename (dir, "applications", basename, NULL);
61 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
62 g_free (path);
63 return NULL;
64 }
65
66 return path;
67 }
68
69 static char *
_panel_g_lookup_in_data_dirs_internal(const char * basename,LookupInDir lookup)70 _panel_g_lookup_in_data_dirs_internal (const char *basename,
71 LookupInDir lookup)
72 {
73 const char * const *system_data_dirs;
74 const char *user_data_dir;
75 char *retval;
76 int i;
77
78 user_data_dir = g_get_user_data_dir ();
79 system_data_dirs = g_get_system_data_dirs ();
80
81 if ((retval = lookup (basename, user_data_dir)))
82 return retval;
83
84 for (i = 0; system_data_dirs[i]; i++)
85 if ((retval = lookup (basename, system_data_dirs[i])))
86 return retval;
87
88 return NULL;
89 }
90
91 char *
panel_g_lookup_in_data_dirs(const char * basename)92 panel_g_lookup_in_data_dirs (const char *basename)
93 {
94 return _panel_g_lookup_in_data_dirs_internal (basename,
95 _lookup_in_dir);
96 }
97
98 char *
panel_g_lookup_in_applications_dirs(const char * basename)99 panel_g_lookup_in_applications_dirs (const char *basename)
100 {
101 return _panel_g_lookup_in_data_dirs_internal (basename,
102 _lookup_in_applications_subdir);
103 }
104
105 /* Copied from evolution-data-server/libedataserver/e-util.c:
106 * e_util_unicode_get_utf8() */
107 static char *
_unicode_get_utf8(const char * text,gunichar * out)108 _unicode_get_utf8 (const char *text, gunichar *out)
109 {
110 *out = g_utf8_get_char (text);
111 return (*out == (gunichar)-1) ? NULL : g_utf8_next_char (text);
112 }
113
114 /* Copied from evolution-data-server/libedataserver/e-util.c:
115 * e_util_utf8_strstrcase() */
116 const char *
panel_g_utf8_strstrcase(const char * haystack,const char * needle)117 panel_g_utf8_strstrcase (const char *haystack, const char *needle)
118 {
119 gunichar *nuni;
120 gunichar unival;
121 gint nlen;
122 const char *o, *p;
123
124 if (haystack == NULL) return NULL;
125 if (needle == NULL) return NULL;
126 if (strlen (needle) == 0) return haystack;
127 if (strlen (haystack) == 0) return NULL;
128
129 nuni = g_alloca (sizeof (gunichar) * strlen (needle));
130
131 nlen = 0;
132 for (p = _unicode_get_utf8 (needle, &unival);
133 p && unival;
134 p = _unicode_get_utf8 (p, &unival)) {
135 nuni[nlen++] = g_unichar_tolower (unival);
136 }
137 /* NULL means there was illegal utf-8 sequence */
138 if (!p) return NULL;
139
140 o = haystack;
141 for (p = _unicode_get_utf8 (o, &unival);
142 p && unival;
143 p = _unicode_get_utf8 (p, &unival)) {
144 gint sc;
145 sc = g_unichar_tolower (unival);
146 /* We have valid stripped char */
147 if (sc == nuni[0]) {
148 const char *q = p;
149 gint npos = 1;
150 while (npos < nlen) {
151 q = _unicode_get_utf8 (q, &unival);
152 if (!q || !unival) return NULL;
153 sc = g_unichar_tolower (unival);
154 if (sc != nuni[npos]) break;
155 npos++;
156 }
157 if (npos == nlen) {
158 return o;
159 }
160 }
161 o = p;
162 }
163
164 return NULL;
165 }
166