Parent Directory | Revision Log
Tests with fremantle copy'n paste
1 | harbaum | 1 | /* |
2 | * Copyright (C) 2008 Till Harbaum <till@harbaum.org>. | ||
3 | * | ||
4 | * This file is part of GPXView. | ||
5 | * | ||
6 | * GPXView is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, either version 3 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GPXView is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with GPXView. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "gpxview.h" | ||
21 | harbaum | 230 | |
22 | // #undef PANNABLE_HTML | ||
23 | |||
24 | #ifdef FREMANTLE | ||
25 | harbaum | 229 | #include <hildon/hildon-banner.h> |
26 | harbaum | 230 | #include <hildon/hildon-note.h> |
27 | #endif | ||
28 | harbaum | 1 | |
29 | typedef struct load_context { | ||
30 | int active; | ||
31 | GMutex *mutex; | ||
32 | GtkWidget *view; | ||
33 | char *url, *path; | ||
34 | GtkHTMLStream *stream; | ||
35 | struct load_context *next; | ||
36 | } load_context_t; | ||
37 | |||
38 | typedef struct { | ||
39 | appdata_t *appdata; | ||
40 | cache_t *cache; | ||
41 | GtkWidget *view; | ||
42 | load_context_t *load_context; | ||
43 | } http_context_t; | ||
44 | |||
45 | static unsigned long name_hash(const char *name) { | ||
46 | unsigned long val = 0; | ||
47 | |||
48 | while(*name) { | ||
49 | val = (val<<8) ^ (val >> 24) ^ (*name & 0xff); | ||
50 | name++; | ||
51 | } | ||
52 | |||
53 | return val; | ||
54 | } | ||
55 | |||
56 | void release_load_context(GThread *self, load_context_t *context) { | ||
57 | /* this must be atomar, so acquire a lock */ | ||
58 | |||
59 | printf("%p: freeing context at %p\n", self, context); | ||
60 | |||
61 | g_mutex_lock(context->mutex); | ||
62 | |||
63 | /* don't do much if the other thread still uses this */ | ||
64 | if(context->active) { | ||
65 | printf(" still active -> just close link\n"); | ||
66 | |||
67 | /* close link to view as the thread is either done or */ | ||
68 | /* main wants to close the view */ | ||
69 | gtk_html_end(GTK_HTML(context->view), context->stream, | ||
70 | GTK_HTML_STREAM_OK); | ||
71 | |||
72 | context->active = FALSE; | ||
73 | g_mutex_unlock(context->mutex); | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | /* ok, other thread is also gone -> we can destroy everything */ | ||
78 | printf(" not active -> destroy\n"); | ||
79 | |||
80 | /* just free everything */ | ||
81 | g_mutex_unlock(context->mutex); | ||
82 | free(context->url); | ||
83 | free(context->path); | ||
84 | free(context); | ||
85 | } | ||
86 | |||
87 | gpointer loader_thread(gpointer data) { | ||
88 | GThread *self = g_thread_self(); | ||
89 | |||
90 | GnomeVFSResult result; | ||
91 | GnomeVFSHandle *handle; | ||
92 | char buffer[4096]; | ||
93 | GnomeVFSFileSize bytes_read; | ||
94 | |||
95 | load_context_t *context = (load_context_t*)data; | ||
96 | |||
97 | printf("%p: loader thread for %s running\n", self, context->url); | ||
98 | |||
99 | result = gnome_vfs_open(&handle, context->url, GNOME_VFS_OPEN_READ); | ||
100 | if(result != GNOME_VFS_OK) { | ||
101 | g_print("%p: open error: %s\n", self, gnome_vfs_result_to_string(result)); | ||
102 | |||
103 | release_load_context(self, context); | ||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | /* try to open file for writing */ | ||
108 | FILE *f = fopen(context->path, "wb"); | ||
109 | int running = TRUE; | ||
110 | |||
111 | do { | ||
112 | result = gnome_vfs_read(handle, buffer, sizeof(buffer)-1, &bytes_read); | ||
113 | if((result == GNOME_VFS_OK) && (bytes_read > 0)) { | ||
114 | |||
115 | /* update local "running" variable from shared variable */ | ||
116 | if(running) { | ||
117 | g_mutex_lock(context->mutex); | ||
118 | running = context->active; | ||
119 | g_mutex_unlock(context->mutex); | ||
120 | } | ||
121 | |||
122 | if(running) | ||
123 | gtk_html_write(GTK_HTML(context->view), | ||
124 | context->stream, buffer, bytes_read); | ||
125 | |||
126 | /* and also write local file */ | ||
127 | if(f) fwrite(buffer, 1l, bytes_read, f); | ||
128 | } | ||
129 | } while((result == GNOME_VFS_OK) && (bytes_read > 0) && running); | ||
130 | |||
131 | if(f) fclose(f); | ||
132 | |||
133 | gnome_vfs_close(handle); | ||
134 | |||
135 | /* this file is likely incomplete, remove it */ | ||
136 | if(!running) { | ||
137 | printf("%p: thread killed, removing imcomplete cached image\n", self); | ||
138 | remove(context->path); | ||
139 | release_load_context(self, context); | ||
140 | return NULL; | ||
141 | } | ||
142 | |||
143 | printf("%p: loader thread successfully finished\n", self); | ||
144 | release_load_context(self, context); | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | harbaum | 230 | #ifdef ENABLE_BROWSER_INTERFACE |
149 | static void on_link_clicked(GtkHTML *html, const gchar *url, | ||
150 | gpointer data) { | ||
151 | |||
152 | appdata_t *appdata = (appdata_t*)data; | ||
153 | |||
154 | #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5) | ||
155 | GtkWidget *dialog = gtk_message_dialog_new( | ||
156 | GTK_WINDOW(appdata->window), | ||
157 | GTK_DIALOG_DESTROY_WITH_PARENT, | ||
158 | GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, | ||
159 | _("Open link on external browser?")); | ||
160 | gboolean yes = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES); | ||
161 | #else | ||
162 | GtkWidget *dialog = | ||
163 | hildon_note_new_confirmation(GTK_WINDOW(appdata->window), | ||
164 | _("Open link in external browser?")); | ||
165 | gboolean yes = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK); | ||
166 | #endif | ||
167 | |||
168 | gtk_widget_destroy(dialog); | ||
169 | |||
170 | if(yes) | ||
171 | browser_url(appdata, (char*)url); | ||
172 | } | ||
173 | #endif | ||
174 | |||
175 | harbaum | 1 | static void on_request_url(GtkHTML *html, const gchar *url, |
176 | GtkHTMLStream *stream, gpointer data) { | ||
177 | char buffer[4096]; | ||
178 | GnomeVFSFileSize bytes_read; | ||
179 | harbaum | 230 | |
180 | harbaum | 1 | http_context_t *context = (http_context_t*)data; |
181 | |||
182 | if(context->cache) { | ||
183 | /* try to build local path */ | ||
184 | char *path = malloc(strlen(context->appdata->image_path)+ | ||
185 | strlen(context->cache->id)+ | ||
186 | 14); /* strlen("/xxxxxxxx.xxx\0") == 14 */ | ||
187 | |||
188 | strcpy(path, context->appdata->image_path); | ||
189 | strcat(path, context->cache->id); | ||
190 | sprintf(path+strlen(path), "/%lx", name_hash(url)); | ||
191 | |||
192 | /* only append extension if there's a useful one up to three chars ... */ | ||
193 | char *dot = strrchr(url, '.'); | ||
194 | if(dot) | ||
195 | if(strlen(dot) <= 4) | ||
196 | strcat(path, dot); | ||
197 | |||
198 | printf("cache name = %s\n", path); | ||
199 | if(g_file_test(path, G_FILE_TEST_EXISTS)) { | ||
200 | printf("image file exists!\n"); | ||
201 | |||
202 | FILE *f = fopen(path, "rb"); | ||
203 | |||
204 | while ((bytes_read = fread(buffer, 1, sizeof(buffer), f)) != 0) { | ||
205 | |||
206 | gtk_html_write(GTK_HTML(context->view), | ||
207 | stream, buffer, bytes_read); | ||
208 | |||
209 | while (gtk_events_pending ()) | ||
210 | gtk_main_iteration (); | ||
211 | } | ||
212 | fclose(f); | ||
213 | |||
214 | } else { | ||
215 | harbaum | 12 | printf("image file doesn't exist, starting extra thread!\n"); |
216 | harbaum | 1 | |
217 | harbaum | 12 | checkdir(path); |
218 | |||
219 | /* walk to end of list */ | ||
220 | load_context_t **load_context = &(context->load_context); | ||
221 | while(*load_context) | ||
222 | load_context = &(*load_context)->next; | ||
223 | |||
224 | *load_context = g_new0(load_context_t, 1); | ||
225 | |||
226 | (*load_context)->url = strdup(url); | ||
227 | (*load_context)->path = strdup(path); | ||
228 | (*load_context)->view = context->view; | ||
229 | (*load_context)->stream = stream; | ||
230 | (*load_context)->next = NULL; | ||
231 | (*load_context)->active = TRUE; | ||
232 | (*load_context)->mutex = g_mutex_new(); | ||
233 | |||
234 | g_thread_create(loader_thread, *load_context, TRUE, NULL); | ||
235 | return; | ||
236 | harbaum | 1 | } |
237 | } else { | ||
238 | /* not a cache, maybe help, so load images from icon directory */ | ||
239 | |||
240 | /* try to build local path */ | ||
241 | char *path = malloc(strlen(ICONPATH)+strlen(url)+1); | ||
242 | |||
243 | strcpy(path, ICONPATH); | ||
244 | strcat(path, url); | ||
245 | if(!g_file_test(path, G_FILE_TEST_EXISTS)) { | ||
246 | strcpy(path, "./icons/"); | ||
247 | strcat(path, url); | ||
248 | } | ||
249 | |||
250 | if(g_file_test(path, G_FILE_TEST_EXISTS)) { | ||
251 | FILE *f = fopen(path, "rb"); | ||
252 | |||
253 | while ((bytes_read = fread(buffer, 1, sizeof(buffer), f)) != 0) { | ||
254 | gtk_html_write(GTK_HTML(context->view), | ||
255 | stream, buffer, bytes_read); | ||
256 | |||
257 | while (gtk_events_pending ()) | ||
258 | gtk_main_iteration (); | ||
259 | } | ||
260 | fclose(f); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | gtk_html_end(GTK_HTML(context->view), stream, GTK_HTML_STREAM_OK); | ||
265 | } | ||
266 | |||
267 | /* notify all open html views of zoom event */ | ||
268 | void html_zoom(appdata_t *appdata, gboolean in) { | ||
269 | struct html_view *html_view = appdata->html_view; | ||
270 | |||
271 | while(html_view) { | ||
272 | printf("zoom notify view %p\n", html_view->view); | ||
273 | |||
274 | if(in) gtk_html_zoom_in(GTK_HTML(html_view->view)); | ||
275 | else gtk_html_zoom_out(GTK_HTML(html_view->view)); | ||
276 | |||
277 | html_view = html_view->next; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | harbaum | 2 | #ifndef NO_COPY_N_PASTE |
282 | harbaum | 1 | static void on_destroy_textview(GtkWidget *widget, gpointer data) { |
283 | appdata_t *appdata = (appdata_t*)data; | ||
284 | int destroy_active = FALSE; | ||
285 | |||
286 | /* only do this if main windows hasn't already been destroyed */ | ||
287 | if(!appdata->window) { | ||
288 | printf("detroy_textview: main window is gone\n"); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | if(!appdata->active_buffer) | ||
293 | printf("Destroy, but there was no active buffer!\n"); | ||
294 | else { | ||
295 | if(GTK_WIDGET_TYPE(widget) == GTK_TYPE_TEXT_VIEW) { | ||
296 | printf("destroying textview\n"); | ||
297 | |||
298 | if(appdata->active_buffer == | ||
299 | gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget))) { | ||
300 | printf("This was the active buffer\n"); | ||
301 | destroy_active = TRUE; | ||
302 | } | ||
303 | } else { | ||
304 | if(widget == (GtkWidget*)appdata->active_buffer) { | ||
305 | printf("This was the active html view\n"); | ||
306 | destroy_active = TRUE; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | if(destroy_active) { | ||
312 | appdata->active_buffer = NULL; | ||
313 | |||
314 | gtk_widget_set_sensitive(appdata->menu_cut, FALSE); | ||
315 | gtk_widget_set_sensitive(appdata->menu_copy, FALSE); | ||
316 | gtk_widget_set_sensitive(appdata->menu_paste, FALSE); | ||
317 | } | ||
318 | } | ||
319 | harbaum | 2 | #endif |
320 | harbaum | 1 | |
321 | static void on_destroy_htmlview(GtkWidget *widget, gpointer data) { | ||
322 | http_context_t *context = (http_context_t*)data; | ||
323 | |||
324 | printf("destroying html context\n"); | ||
325 | // printf("associated view = %p\n", context->view); | ||
326 | |||
327 | struct html_view **h = &(context->appdata->html_view); | ||
328 | |||
329 | while(*h && (*h)->view != context->view) | ||
330 | h = &((*h)->next); | ||
331 | |||
332 | g_assert(h); | ||
333 | |||
334 | /* remove entry from chain */ | ||
335 | void *tmp = *h; | ||
336 | *h = (*h)->next; | ||
337 | free(tmp); | ||
338 | |||
339 | load_context_t *load_context = context->load_context; | ||
340 | while(load_context) { | ||
341 | printf("found an associated thread\n"); | ||
342 | |||
343 | load_context_t *tmp_context = load_context->next; | ||
344 | release_load_context(NULL, load_context); | ||
345 | load_context = tmp_context; | ||
346 | } | ||
347 | |||
348 | harbaum | 2 | #ifndef NO_COPY_N_PASTE |
349 | harbaum | 1 | on_destroy_textview(widget, context->appdata); |
350 | harbaum | 2 | #endif |
351 | harbaum | 1 | |
352 | /* destroy context */ | ||
353 | free(data); | ||
354 | } | ||
355 | |||
356 | harbaum | 2 | #ifndef NO_COPY_N_PASTE |
357 | harbaum | 1 | static gboolean focus_in(GtkWidget *widget, GdkEventFocus *event, |
358 | gpointer data) { | ||
359 | appdata_t *appdata = (appdata_t*)data; | ||
360 | |||
361 | printf("focus in!\n"); | ||
362 | |||
363 | /* these buffers are read-only, thus only "copy" is enabled */ | ||
364 | gtk_widget_set_sensitive(appdata->menu_cut, FALSE); | ||
365 | gtk_widget_set_sensitive(appdata->menu_copy, TRUE); | ||
366 | gtk_widget_set_sensitive(appdata->menu_paste, FALSE); | ||
367 | |||
368 | if(GTK_WIDGET_TYPE(widget) == GTK_TYPE_TEXT_VIEW) { | ||
369 | appdata->active_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); | ||
370 | } else if(GTK_WIDGET_TYPE(widget) == gtk_html_get_type()) { | ||
371 | appdata->active_buffer = (GtkTextBuffer*)widget; | ||
372 | } else { | ||
373 | printf("not a text nor a html view\n"); | ||
374 | } | ||
375 | |||
376 | return FALSE; | ||
377 | } | ||
378 | |||
379 | void html_copy_to_clipboard(appdata_t *appdata) { | ||
380 | gtk_html_copy(GTK_HTML(appdata->active_buffer)); | ||
381 | } | ||
382 | harbaum | 2 | #endif |
383 | harbaum | 1 | |
384 | harbaum | 230 | #ifdef FREMANTLE |
385 | harbaum | 229 | static void |
386 | tap_and_hold_cb (GtkWidget *widget, gpointer user_data) { | ||
387 | appdata_t *appdata = (appdata_t*)user_data; | ||
388 | |||
389 | harbaum | 230 | /* the HildonTextView becomes semi-copy'n pasteable if we enable */ |
390 | /* the cursor */ | ||
391 | if(GTK_WIDGET_TYPE(widget) == HILDON_TYPE_TEXT_VIEW) { | ||
392 | gboolean state = gtk_text_view_get_cursor_visible(GTK_TEXT_VIEW(widget)); | ||
393 | gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(widget), !state); | ||
394 | |||
395 | hildon_banner_show_information(GTK_WIDGET(appdata->window), | ||
396 | NULL, state?"Cursor disabled":"Cursor enabled"); | ||
397 | |||
398 | return; | ||
399 | } | ||
400 | |||
401 | GtkWidget *parent = widget->parent; | ||
402 | |||
403 | /* check if the parent actually is a hildonpannablearea */ | ||
404 | if(GTK_WIDGET_TYPE(parent) != HILDON_TYPE_PANNABLE_AREA) { | ||
405 | printf("parent is not pannable area, ignoring event\n"); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | /* lets assume parent is a pannable area ... */ | ||
410 | |||
411 | hildon_banner_show_information(GTK_WIDGET(appdata->window), | ||
412 | NULL, "Copy'n paste is not working in maemo5"); | ||
413 | |||
414 | #if 0 | ||
415 | gboolean enabled = FALSE; | ||
416 | g_object_get(parent, "enabled", &enabled, NULL); | ||
417 | enabled = !enabled; | ||
418 | g_object_set(parent, "enabled", enabled, NULL); | ||
419 | |||
420 | hildon_banner_show_information(GTK_WIDGET(appdata->window), | ||
421 | NULL, enabled?"enabled":"disabled"); | ||
422 | #endif | ||
423 | harbaum | 1 | } |
424 | #endif | ||
425 | |||
426 | /* the cache descriptions are not valid html and need some surrounding stuff */ | ||
427 | static const char *html_start = "<html><head>" | ||
428 | "<meta http-equiv=content-type content=\"text/html; charset=UTF-8\">" | ||
429 | "</head></body>"; | ||
430 | static const char *html_end = "</body></html>"; | ||
431 | |||
432 | GtkWidget *html_view(appdata_t *appdata, char *text, | ||
433 | harbaum | 140 | html_mode_t mode, gboolean scrollwin, |
434 | harbaum | 1 | cache_t *cache, char *anchor) { |
435 | GtkWidget *view; | ||
436 | |||
437 | harbaum | 140 | if(mode == HTML_HTML) { |
438 | harbaum | 1 | http_context_t *context = g_new0(http_context_t, 1); |
439 | context->appdata = appdata; | ||
440 | context->cache = cache; | ||
441 | |||
442 | context->view = view = gtk_html_new(); | ||
443 | |||
444 | harbaum | 230 | #ifndef PANNABLE_HTML |
445 | // gtk_html_set_auto_panning(GTK_HTML(view), TRUE); | ||
446 | #else | ||
447 | gtk_html_set_auto_panning(GTK_HTML(view), FALSE); | ||
448 | #endif | ||
449 | |||
450 | #ifdef FREMANTLE | ||
451 | /* allow selection does not allow anything, but disables auto panning ... */ | ||
452 | /* even worse: frequently causes the device to reboot */ | ||
453 | // gtk_html_allow_selection(GTK_HTML(view), TRUE); | ||
454 | #endif | ||
455 | |||
456 | harbaum | 1 | /* create a callback to load images only if a cache has been given */ |
457 | /* so that images can be cached/stored appropriately */ | ||
458 | g_signal_connect(G_OBJECT(view), "url_requested", | ||
459 | G_CALLBACK(on_request_url), context); | ||
460 | |||
461 | harbaum | 230 | #ifdef ENABLE_BROWSER_INTERFACE |
462 | g_signal_connect(G_OBJECT(view), "link_clicked", | ||
463 | G_CALLBACK(on_link_clicked), context->appdata); | ||
464 | #endif | ||
465 | |||
466 | harbaum | 1 | GtkHTMLStream *stream = gtk_html_begin(GTK_HTML(view)); |
467 | |||
468 | gtk_html_write(GTK_HTML(view), stream, html_start, strlen(html_start)); | ||
469 | gtk_html_write(GTK_HTML(view), stream, text, strlen(text)); | ||
470 | gtk_html_write(GTK_HTML(view), stream, html_end, strlen(html_end)); | ||
471 | gtk_html_end(GTK_HTML(view), stream, GTK_HTML_STREAM_OK); | ||
472 | |||
473 | if(anchor) { | ||
474 | while(gtk_events_pending()) | ||
475 | gtk_main_iteration (); | ||
476 | |||
477 | gtk_html_jump_to_anchor(GTK_HTML(context->view), anchor); | ||
478 | } | ||
479 | |||
480 | /* register this html view */ | ||
481 | struct html_view **h = &(appdata->html_view); | ||
482 | while(*h) h = &((*h)->next); | ||
483 | *h = g_new0(struct html_view, 1); | ||
484 | (*h)->view = view; | ||
485 | |||
486 | harbaum | 230 | #ifdef FREMANTLE |
487 | harbaum | 229 | gtk_widget_tap_and_hold_setup(GTK_WIDGET(view), NULL, NULL, 0); |
488 | harbaum | 230 | g_signal_connect(G_OBJECT(view), "tap-and-hold", |
489 | G_CALLBACK(tap_and_hold_cb), appdata); | ||
490 | harbaum | 1 | #endif |
491 | |||
492 | g_signal_connect(G_OBJECT(view), "destroy", | ||
493 | G_CALLBACK(on_destroy_htmlview), context); | ||
494 | } else { | ||
495 | GtkTextBuffer *buffer = gtk_text_buffer_new(NULL); | ||
496 | gtk_text_buffer_set_text(buffer, text, strlen(text)); | ||
497 | |||
498 | harbaum | 8 | #ifndef USE_HILDON_TEXT_VIEW |
499 | harbaum | 1 | view = gtk_text_view_new_with_buffer(buffer); |
500 | #else | ||
501 | view = hildon_text_view_new(); | ||
502 | hildon_text_view_set_buffer(HILDON_TEXT_VIEW(view), buffer); | ||
503 | harbaum | 229 | |
504 | gtk_widget_tap_and_hold_setup(GTK_WIDGET(view), NULL, NULL, 0); | ||
505 | harbaum | 230 | g_signal_connect(G_OBJECT(view), "tap-and-hold", |
506 | G_CALLBACK(tap_and_hold_cb), appdata); | ||
507 | harbaum | 1 | #endif |
508 | |||
509 | gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD); | ||
510 | gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE); | ||
511 | gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE); | ||
512 | |||
513 | harbaum | 163 | /* make this look nicer in fremantle and not just black-on-white */ |
514 | /* just use the default style */ | ||
515 | harbaum | 226 | #ifdef USE_STACKABLE_WINDOW |
516 | /* in fremantle this is really tricky and we need to inherit the */ | ||
517 | /* style from the topmost window in the stack */ | ||
518 | HildonWindowStack *stack = hildon_window_stack_get_default(); | ||
519 | GList *list = hildon_window_stack_get_windows(stack); | ||
520 | gtk_widget_set_style(view, GTK_WIDGET(list->data)->style); | ||
521 | g_list_free(list); | ||
522 | harbaum | 163 | #else |
523 | harbaum | 226 | gtk_widget_set_style(view, GTK_WIDGET(appdata->window)->style); |
524 | harbaum | 163 | #endif |
525 | |||
526 | harbaum | 2 | #ifndef NO_COPY_N_PASTE |
527 | harbaum | 1 | g_signal_connect(G_OBJECT(view), "destroy", |
528 | G_CALLBACK(on_destroy_textview), appdata); | ||
529 | harbaum | 2 | #endif |
530 | harbaum | 1 | } |
531 | |||
532 | harbaum | 2 | #ifndef NO_COPY_N_PASTE |
533 | harbaum | 1 | g_signal_connect(G_OBJECT(view), "focus-in-event", |
534 | G_CALLBACK(focus_in), appdata); | ||
535 | harbaum | 2 | #endif |
536 | harbaum | 1 | |
537 | if(scrollwin) { | ||
538 | #ifndef USE_PANNABLE_AREA | ||
539 | GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); | ||
540 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), | ||
541 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | ||
542 | gtk_container_add(GTK_CONTAINER(scrolled_window), view); | ||
543 | |||
544 | return scrolled_window; | ||
545 | #else | ||
546 | #ifndef PANNABLE_HTML | ||
547 | harbaum | 140 | if(mode == HTML_HTML) { |
548 | harbaum | 1 | GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
549 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), | ||
550 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | ||
551 | gtk_container_add(GTK_CONTAINER(scrolled_window), view); | ||
552 | return scrolled_window; | ||
553 | } else | ||
554 | #endif | ||
555 | { | ||
556 | GtkWidget *pannable_area = hildon_pannable_area_new(); | ||
557 | gtk_container_add(GTK_CONTAINER(pannable_area), view); | ||
558 | return pannable_area; | ||
559 | } | ||
560 | #endif | ||
561 | } | ||
562 | |||
563 | return view; | ||
564 | } | ||
565 |