19 |
|
|
20 |
#include "gpxview.h" |
#include "gpxview.h" |
21 |
|
|
22 |
|
// #undef PANNABLE_HTML |
23 |
|
|
24 |
|
#ifdef FREMANTLE |
25 |
|
#include <hildon/hildon-banner.h> |
26 |
|
#include <hildon/hildon-note.h> |
27 |
|
#endif |
28 |
|
|
29 |
typedef struct load_context { |
typedef struct load_context { |
30 |
int active; |
int active; |
31 |
GMutex *mutex; |
GMutex *mutex; |
145 |
return NULL; |
return NULL; |
146 |
} |
} |
147 |
|
|
148 |
|
#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 |
static void on_request_url(GtkHTML *html, const gchar *url, |
static void on_request_url(GtkHTML *html, const gchar *url, |
176 |
GtkHTMLStream *stream, gpointer data) { |
GtkHTMLStream *stream, gpointer data) { |
177 |
char buffer[4096]; |
char buffer[4096]; |
178 |
GnomeVFSFileSize bytes_read; |
GnomeVFSFileSize bytes_read; |
179 |
|
|
180 |
http_context_t *context = (http_context_t*)data; |
http_context_t *context = (http_context_t*)data; |
181 |
|
|
182 |
if(context->cache) { |
if(context->cache) { |
212 |
fclose(f); |
fclose(f); |
213 |
|
|
214 |
} else { |
} else { |
215 |
if(context->appdata->load_images) { |
printf("image file doesn't exist, starting extra thread!\n"); |
|
printf("image file doesn't exist, starting extra thread!\n"); |
|
|
|
|
|
checkdir(path); |
|
|
|
|
|
/* walk to end of list */ |
|
|
load_context_t **load_context = &(context->load_context); |
|
|
while(*load_context) |
|
|
load_context = &(*load_context)->next; |
|
|
|
|
|
*load_context = g_new0(load_context_t, 1); |
|
|
|
|
|
(*load_context)->url = strdup(url); |
|
|
(*load_context)->path = strdup(path); |
|
|
(*load_context)->view = context->view; |
|
|
(*load_context)->stream = stream; |
|
|
(*load_context)->next = NULL; |
|
|
(*load_context)->active = TRUE; |
|
|
(*load_context)->mutex = g_mutex_new(); |
|
216 |
|
|
217 |
g_thread_create(loader_thread, *load_context, TRUE, NULL); |
checkdir(path); |
218 |
return; |
|
219 |
} else |
/* walk to end of list */ |
220 |
g_print("Image loading disabled\n"); |
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 |
} |
} |
237 |
} else { |
} else { |
238 |
/* not a cache, maybe help, so load images from icon directory */ |
/* not a cache, maybe help, so load images from icon directory */ |
278 |
} |
} |
279 |
} |
} |
280 |
|
|
281 |
|
#ifndef NO_COPY_N_PASTE |
282 |
static void on_destroy_textview(GtkWidget *widget, gpointer data) { |
static void on_destroy_textview(GtkWidget *widget, gpointer data) { |
283 |
appdata_t *appdata = (appdata_t*)data; |
appdata_t *appdata = (appdata_t*)data; |
284 |
int destroy_active = FALSE; |
int destroy_active = FALSE; |
316 |
gtk_widget_set_sensitive(appdata->menu_paste, FALSE); |
gtk_widget_set_sensitive(appdata->menu_paste, FALSE); |
317 |
} |
} |
318 |
} |
} |
319 |
|
#endif |
320 |
|
|
321 |
static void on_destroy_htmlview(GtkWidget *widget, gpointer data) { |
static void on_destroy_htmlview(GtkWidget *widget, gpointer data) { |
322 |
http_context_t *context = (http_context_t*)data; |
http_context_t *context = (http_context_t*)data; |
345 |
load_context = tmp_context; |
load_context = tmp_context; |
346 |
} |
} |
347 |
|
|
348 |
|
#ifndef NO_COPY_N_PASTE |
349 |
on_destroy_textview(widget, context->appdata); |
on_destroy_textview(widget, context->appdata); |
350 |
|
#endif |
351 |
|
|
352 |
/* destroy context */ |
/* destroy context */ |
353 |
free(data); |
free(data); |
354 |
} |
} |
355 |
|
|
356 |
|
#ifndef NO_COPY_N_PASTE |
357 |
static gboolean focus_in(GtkWidget *widget, GdkEventFocus *event, |
static gboolean focus_in(GtkWidget *widget, GdkEventFocus *event, |
358 |
gpointer data) { |
gpointer data) { |
359 |
appdata_t *appdata = (appdata_t*)data; |
appdata_t *appdata = (appdata_t*)data; |
379 |
void html_copy_to_clipboard(appdata_t *appdata) { |
void html_copy_to_clipboard(appdata_t *appdata) { |
380 |
gtk_html_copy(GTK_HTML(appdata->active_buffer)); |
gtk_html_copy(GTK_HTML(appdata->active_buffer)); |
381 |
} |
} |
382 |
|
#endif |
383 |
|
|
384 |
/* panning a gtkhtml view currently doesn't work well */ |
#ifdef FREMANTLE |
385 |
#undef PANNABLE_HTML |
static void |
386 |
|
tap_and_hold_cb (GtkWidget *widget, gpointer user_data) { |
387 |
|
appdata_t *appdata = (appdata_t*)user_data; |
388 |
|
|
389 |
|
/* 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 |
#ifdef PANNABLE_HTML |
hildon_banner_show_information(GTK_WIDGET(appdata->window), |
396 |
/* eat the button events */ |
NULL, state?"Cursor disabled":"Cursor enabled"); |
397 |
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, |
|
398 |
gpointer user_data) { |
return; |
399 |
return TRUE; |
} |
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 |
} |
} |
424 |
#endif |
#endif |
425 |
|
|
430 |
static const char *html_end = "</body></html>"; |
static const char *html_end = "</body></html>"; |
431 |
|
|
432 |
GtkWidget *html_view(appdata_t *appdata, char *text, |
GtkWidget *html_view(appdata_t *appdata, char *text, |
433 |
gboolean is_html, gboolean scrollwin, |
html_mode_t mode, gboolean scrollwin, |
434 |
cache_t *cache, char *anchor) { |
cache_t *cache, char *anchor) { |
435 |
GtkWidget *view; |
GtkWidget *view; |
436 |
|
|
437 |
if(is_html) { |
if(mode == HTML_HTML) { |
438 |
http_context_t *context = g_new0(http_context_t, 1); |
http_context_t *context = g_new0(http_context_t, 1); |
439 |
context->appdata = appdata; |
context->appdata = appdata; |
440 |
context->cache = cache; |
context->cache = cache; |
441 |
|
|
442 |
context->view = view = gtk_html_new(); |
context->view = view = gtk_html_new(); |
443 |
|
|
444 |
|
#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 |
/* create a callback to load images only if a cache has been given */ |
/* create a callback to load images only if a cache has been given */ |
457 |
/* so that images can be cached/stored appropriately */ |
/* so that images can be cached/stored appropriately */ |
458 |
g_signal_connect(G_OBJECT(view), "url_requested", |
g_signal_connect(G_OBJECT(view), "url_requested", |
459 |
G_CALLBACK(on_request_url), context); |
G_CALLBACK(on_request_url), context); |
460 |
|
|
461 |
|
#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 |
GtkHTMLStream *stream = gtk_html_begin(GTK_HTML(view)); |
GtkHTMLStream *stream = gtk_html_begin(GTK_HTML(view)); |
467 |
|
|
468 |
gtk_html_write(GTK_HTML(view), stream, html_start, strlen(html_start)); |
gtk_html_write(GTK_HTML(view), stream, html_start, strlen(html_start)); |
483 |
*h = g_new0(struct html_view, 1); |
*h = g_new0(struct html_view, 1); |
484 |
(*h)->view = view; |
(*h)->view = view; |
485 |
|
|
486 |
#ifdef PANNABLE_HTML |
#ifdef FREMANTLE |
487 |
/* this causes finger scrolling to work nicely but also prevents */ |
gtk_widget_tap_and_hold_setup(GTK_WIDGET(view), NULL, NULL, 0); |
488 |
/* copy'n paste from working correctly */ |
g_signal_connect(G_OBJECT(view), "tap-and-hold", |
489 |
gtk_widget_set_sensitive(GTK_WIDGET(view), FALSE); |
G_CALLBACK(tap_and_hold_cb), appdata); |
|
|
|
|
g_signal_connect(G_OBJECT(view), "button-press-event", |
|
|
G_CALLBACK(on_button_press), NULL); |
|
490 |
#endif |
#endif |
491 |
|
|
492 |
g_signal_connect(G_OBJECT(view), "destroy", |
g_signal_connect(G_OBJECT(view), "destroy", |
495 |
GtkTextBuffer *buffer = gtk_text_buffer_new(NULL); |
GtkTextBuffer *buffer = gtk_text_buffer_new(NULL); |
496 |
gtk_text_buffer_set_text(buffer, text, strlen(text)); |
gtk_text_buffer_set_text(buffer, text, strlen(text)); |
497 |
|
|
498 |
#ifndef USE_MAEMO |
#ifndef USE_HILDON_TEXT_VIEW |
499 |
view = gtk_text_view_new_with_buffer(buffer); |
view = gtk_text_view_new_with_buffer(buffer); |
500 |
#else |
#else |
501 |
view = hildon_text_view_new(); |
view = hildon_text_view_new(); |
502 |
hildon_text_view_set_buffer(HILDON_TEXT_VIEW(view), buffer); |
hildon_text_view_set_buffer(HILDON_TEXT_VIEW(view), buffer); |
503 |
|
|
504 |
|
gtk_widget_tap_and_hold_setup(GTK_WIDGET(view), NULL, NULL, 0); |
505 |
|
g_signal_connect(G_OBJECT(view), "tap-and-hold", |
506 |
|
G_CALLBACK(tap_and_hold_cb), appdata); |
507 |
#endif |
#endif |
508 |
|
|
509 |
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD); |
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD); |
510 |
gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE); |
gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE); |
511 |
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE); |
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE); |
512 |
|
|
513 |
|
/* make this look nicer in fremantle and not just black-on-white */ |
514 |
|
/* just use the default style */ |
515 |
|
#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 |
|
#else |
523 |
|
gtk_widget_set_style(view, GTK_WIDGET(appdata->window)->style); |
524 |
|
#endif |
525 |
|
|
526 |
|
#ifndef NO_COPY_N_PASTE |
527 |
g_signal_connect(G_OBJECT(view), "destroy", |
g_signal_connect(G_OBJECT(view), "destroy", |
528 |
G_CALLBACK(on_destroy_textview), appdata); |
G_CALLBACK(on_destroy_textview), appdata); |
529 |
|
#endif |
530 |
} |
} |
531 |
|
|
532 |
|
#ifndef NO_COPY_N_PASTE |
533 |
g_signal_connect(G_OBJECT(view), "focus-in-event", |
g_signal_connect(G_OBJECT(view), "focus-in-event", |
534 |
G_CALLBACK(focus_in), appdata); |
G_CALLBACK(focus_in), appdata); |
535 |
|
#endif |
536 |
|
|
537 |
if(scrollwin) { |
if(scrollwin) { |
538 |
#ifndef USE_PANNABLE_AREA |
#ifndef USE_PANNABLE_AREA |
541 |
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
542 |
gtk_container_add(GTK_CONTAINER(scrolled_window), view); |
gtk_container_add(GTK_CONTAINER(scrolled_window), view); |
543 |
|
|
|
#if 1 |
|
544 |
return scrolled_window; |
return scrolled_window; |
545 |
#else |
#else |
|
GtkWidget *fixed = gtk_fixed_new(); |
|
|
gtk_fixed_put(GTK_FIXED(fixed), scrolled_window, 0, 0); |
|
|
GtkWidget *tbutton = gtk_toggle_button_new_with_label("sel"); |
|
|
gtk_fixed_put(GTK_FIXED(fixed), tbutton, 0, 0); |
|
|
return fixed; |
|
|
#endif |
|
|
#else |
|
546 |
#ifndef PANNABLE_HTML |
#ifndef PANNABLE_HTML |
547 |
if(is_html) { |
if(mode == HTML_HTML) { |
548 |
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
549 |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window), |
550 |
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |