~elementary-os/elementaryos/os-patch-notify-osd-precise

« back to all changes in this revision

Viewing changes to src/util.c

  • Committer: Sergey "Shnatsel" Davidoff
  • Date: 2012-06-18 21:08:31 UTC
  • Revision ID: shnatsel@gmail.com-20120618210831-g6k5y7vecjdylgic
Initial import, version 0.9.34-0ubuntu2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 **3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
 
3
 **      10        20        30        40        50        60        70        80
 
4
 **
 
5
 ** notify-osd
 
6
 **
 
7
 ** util.c - all sorts of helper functions
 
8
 **
 
9
 ** Copyright 2009 Canonical Ltd.
 
10
 **
 
11
 ** Authors:
 
12
 **    Cody Russell <cody.russell@canonical.com>
 
13
 **    Mirco "MacSlow" Mueller <mirco.mueller@canonical.com>
 
14
 **
 
15
 ** This program is free software: you can redistribute it and/or modify it
 
16
 ** under the terms of the GNU General Public License version 3, as published
 
17
 ** by the Free Software Foundation.
 
18
 **
 
19
 ** This program is distributed in the hope that it will be useful, but
 
20
 ** WITHOUT ANY WARRANTY; without even the implied warranties of
 
21
 ** MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
22
 ** PURPOSE.  See the GNU General Public License for more details.
 
23
 **
 
24
 ** You should have received a copy of the GNU General Public License along
 
25
 ** with this program.  If not, see <http://www.gnu.org/licenses/>.
 
26
 **
 
27
 *******************************************************************************/
 
28
 
 
29
#include <string.h>
 
30
#include <glib.h>
 
31
#include <gtk/gtk.h>
 
32
#include <gdk/gdkx.h>
 
33
#include <pango/pango.h>
 
34
#include <cairo.h>
 
35
 
 
36
#define CHARACTER_LT_REGEX            "&(lt;|#60;|#x3c;)"
 
37
#define CHARACTER_GT_REGEX            "&(gt;|#62;|#x3e;)"
 
38
#define CHARACTER_AMP_REGEX           "&(amp;|#38;|#x26;)"
 
39
#define CHARACTER_APOS_REGEX          "&apos;"
 
40
#define CHARACTER_QUOT_REGEX          "&quot;"
 
41
#define CHARACTER_NEWLINE_REGEX       " *((<br[^/>]*/?>|\r|\n)+ *)+"
 
42
 
 
43
#define TAG_MATCH_REGEX     "<(b|i|u|big|a|img|span|s|sub|small|tt|html|qt)\\b[^>]*>(.*?)</\\1>|<(img|span|a)[^>]/>|<(img)[^>]*>"
 
44
#define TAG_REPLACE_REGEX   "<(b|i|u|big|a|img|span|s|sub|small|tt|html|qt)\\b[^>]*>|</(b|i|u|big|a|img|span|s|sub|small|tt|html|qt)>"
 
45
 
 
46
struct _ReplaceMarkupData
 
47
{
 
48
        gchar* regex;
 
49
        gchar* replacement;
 
50
};
 
51
 
 
52
typedef struct _ReplaceMarkupData ReplaceMarkupData;
 
53
 
 
54
static gchar*
 
55
strip_html (const gchar *text, const gchar *match_regex, const gchar* replace_regex)
 
56
{
 
57
        GRegex   *regex;
 
58
        gchar    *ret;
 
59
        gboolean  match = FALSE;
 
60
        GMatchInfo *info = NULL;
 
61
 
 
62
        regex = g_regex_new (match_regex, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
 
63
        match = g_regex_match (regex, text, 0, &info);
 
64
        g_regex_unref (regex);
 
65
 
 
66
        if (match) {
 
67
                regex = g_regex_new (replace_regex, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
 
68
                ret = g_regex_replace (regex, text, -1, 0, "", 0, NULL);
 
69
                g_regex_unref (regex);
 
70
        } else {
 
71
                ret = g_strdup (text);
 
72
        }
 
73
 
 
74
        if (info)
 
75
                g_match_info_free (info);
 
76
 
 
77
        return ret;
 
78
}
 
79
 
 
80
static gchar*
 
81
replace_markup (const gchar *text, const gchar *match_regex, const gchar *replace_text)
 
82
{
 
83
        GRegex *regex;
 
84
        gchar  *ret;
 
85
 
 
86
        regex = g_regex_new (match_regex, G_REGEX_DOTALL | G_REGEX_OPTIMIZE, 0, NULL);
 
87
        ret = g_regex_replace (regex, text, -1, 0, replace_text, 0, NULL);
 
88
        g_regex_unref (regex);
 
89
 
 
90
        return ret;
 
91
}
 
92
 
 
93
gchar*
 
94
filter_text (const gchar *text)
 
95
{
 
96
        gchar *text1;
 
97
 
 
98
        text1 = strip_html (text, TAG_MATCH_REGEX, TAG_REPLACE_REGEX);
 
99
 
 
100
        static ReplaceMarkupData data[] = {
 
101
                { CHARACTER_AMP_REGEX, "&" },
 
102
                { CHARACTER_LT_REGEX, "<" },
 
103
                { CHARACTER_GT_REGEX, ">" },
 
104
                { CHARACTER_APOS_REGEX, "'" },
 
105
                { CHARACTER_QUOT_REGEX, "\"" },
 
106
                { CHARACTER_NEWLINE_REGEX, "\n" }
 
107
                };
 
108
 
 
109
        ReplaceMarkupData* ptr = data;
 
110
        ReplaceMarkupData* end = data + sizeof(data) / sizeof(ReplaceMarkupData);
 
111
        for (; ptr != end; ++ptr) {
 
112
                gchar* tmp = replace_markup (text1, ptr->regex, ptr->replacement);
 
113
                g_free (text1);
 
114
                text1 = tmp;
 
115
        }
 
116
 
 
117
        return text1;
 
118
}
 
119
 
 
120
gchar*
 
121
newline_to_space (const gchar *text)
 
122
{
 
123
        gchar *text1;
 
124
 
 
125
        text1 = strip_html (text, TAG_MATCH_REGEX, TAG_REPLACE_REGEX);
 
126
 
 
127
        static ReplaceMarkupData data[] = {
 
128
                { CHARACTER_NEWLINE_REGEX, " " }
 
129
                };
 
130
 
 
131
        ReplaceMarkupData* ptr = data;
 
132
        ReplaceMarkupData* end = data + sizeof(data) / sizeof(ReplaceMarkupData);
 
133
        for (; ptr != end; ++ptr) {
 
134
                gchar* tmp = replace_markup (text1, ptr->regex, ptr->replacement);
 
135
                g_free (text1);
 
136
                text1 = tmp;
 
137
        }
 
138
 
 
139
        return text1;
 
140
}
 
141
 
 
142
gboolean
 
143
destroy_cloned_surface (cairo_surface_t* surface)
 
144
{
 
145
        gboolean finalref = FALSE;
 
146
        g_return_val_if_fail (surface, FALSE);
 
147
 
 
148
        if (cairo_surface_get_reference_count  (surface) == 1) {
 
149
                g_free (cairo_image_surface_get_data (surface));
 
150
                finalref = TRUE;
 
151
        }
 
152
        cairo_surface_destroy (surface);
 
153
        return finalref;
 
154
}
 
155
 
 
156
cairo_surface_t*
 
157
copy_surface (cairo_surface_t* orig)
 
158
{
 
159
        cairo_surface_t* copy       = NULL;
 
160
        guchar*          pixels_src = NULL;
 
161
        guchar*          pixels_cpy = NULL;
 
162
        cairo_format_t   format;
 
163
        gint             width;
 
164
        gint             height;
 
165
        gint             stride;
 
166
 
 
167
        pixels_src = cairo_image_surface_get_data (orig);
 
168
        if (!pixels_src)
 
169
                return NULL;
 
170
 
 
171
        format = cairo_image_surface_get_format (orig);
 
172
        width  = cairo_image_surface_get_width (orig);
 
173
        height = cairo_image_surface_get_height (orig);
 
174
        stride = cairo_image_surface_get_stride (orig);
 
175
 
 
176
        pixels_cpy = g_malloc0 (stride * height);
 
177
        if (!pixels_cpy)
 
178
                return NULL;
 
179
 
 
180
        memcpy ((void*) pixels_cpy, (void*) pixels_src, height * stride);
 
181
 
 
182
        copy = cairo_image_surface_create_for_data (pixels_cpy,
 
183
                                                    format,
 
184
                                                    width,
 
185
                                                    height,
 
186
                                                    stride);
 
187
 
 
188
        return copy;
 
189
}
 
190
 
 
191
// code of get_wm_name() based in large chunks on www.amsn-project.net
 
192
gchar*
 
193
get_wm_name (Display* dpy)
 
194
{
 
195
        int            screen;
 
196
        Atom           type;
 
197
        int            format;
 
198
        unsigned long  bytes_returned;
 
199
        unsigned long  n_returned;
 
200
        unsigned char* buffer;
 
201
        Window*        child;
 
202
        Window         root;
 
203
        Atom           supwmcheck;
 
204
        Atom           wmname;
 
205
 
 
206
        if (!dpy)
 
207
                return NULL;
 
208
 
 
209
        screen = DefaultScreen (dpy);
 
210
        root = RootWindow (dpy, screen);
 
211
        supwmcheck = XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
 
212
        wmname = XInternAtom (dpy, "_NET_WM_NAME", False);
 
213
 
 
214
        XGetWindowProperty (dpy,
 
215
                            root,
 
216
                            supwmcheck,
 
217
                            0,
 
218
                            8,
 
219
                            False,
 
220
                            AnyPropertyType,
 
221
                            &type,
 
222
                            &format,
 
223
                            &n_returned,
 
224
                            &bytes_returned,
 
225
                            &buffer);
 
226
 
 
227
        child = (Window*) buffer;
 
228
 
 
229
        if (n_returned != 1)
 
230
                return NULL;
 
231
 
 
232
        XGetWindowProperty (dpy,
 
233
                            *child,
 
234
                            wmname,
 
235
                            0,
 
236
                            128,
 
237
                            False,
 
238
                            AnyPropertyType,
 
239
                            &type,
 
240
                            &format,
 
241
                            &n_returned,
 
242
                            &bytes_returned,
 
243
                            &buffer);
 
244
 
 
245
        if (n_returned == 0)
 
246
                return NULL;
 
247
 
 
248
        XFree (child);
 
249
 
 
250
        // example wm-names as reported by get_wm_name()
 
251
        //
 
252
        //  compiz
 
253
        //  Metacity
 
254
        //  Xfwm4
 
255
        //  KWin
 
256
        //  xmonad
 
257
 
 
258
        return (gchar*) buffer;
 
259
}
 
260
 
 
261
GString*
 
262
extract_font_face (const gchar* string)
 
263
{
 
264
        GRegex*     regex      = NULL;
 
265
        GMatchInfo* match_info = NULL;
 
266
        GString*    font_face  = NULL;
 
267
 
 
268
        // sanity check
 
269
        if (!string)
 
270
                return NULL;
 
271
 
 
272
        // extract font-face-name/style
 
273
        font_face = g_string_new ("");
 
274
        if (!font_face)
 
275
                return NULL;
 
276
 
 
277
        // setup regular expression to extract leading text before trailing int
 
278
        regex = g_regex_new ("([A-Z a-z])+", 0, 0, NULL);
 
279
 
 
280
        // walk the string
 
281
        g_regex_match (regex, string, 0, &match_info);
 
282
        while (g_match_info_matches (match_info))
 
283
        {
 
284
                gchar* word = NULL;
 
285
 
 
286
                word = g_match_info_fetch (match_info, 0);
 
287
                if (word)
 
288
                {
 
289
                        g_string_append (font_face, word);
 
290
                        g_free (word);
 
291
                }
 
292
 
 
293
                g_match_info_next (match_info, NULL);
 
294
        }
 
295
 
 
296
        // clean up
 
297
        g_match_info_free (match_info);
 
298
        g_regex_unref (regex);
 
299
 
 
300
        return font_face;
 
301
}