Mercurial > pidgin.yaz
comparison src/gtkimhtml.c @ 7749:ddda7537918e
[gaim-migrate @ 8394]
This is what I did last night. It lets you copy from a WYSIWYG gtkimhtml
(the more useful non-editable gtkimhtml comes next) into anything else
supporting text/html pastes (GtkHTML, Openoffice.org, Mozilla, for example).
Soon you will also be able to paste HTML into one of these suckers too.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Thu, 04 Dec 2003 20:31:49 +0000 |
parents | 9cc221f68107 |
children | 14cc6614af93 |
comparison
equal
deleted
inserted
replaced
7748:8165ab2a00e6 | 7749:ddda7537918e |
---|---|
65 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | 65 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ |
66 #define MAX_FONT_SIZE 7 | 66 #define MAX_FONT_SIZE 7 |
67 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) | 67 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
68 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; | 68 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; |
69 | 69 |
70 enum { | |
71 TARGET_HTML, | |
72 TARGET_UTF8_STRING, | |
73 TARGET_COMPOUND_TEXT, | |
74 TARGET_STRING, | |
75 TARGET_TEXT | |
76 }; | |
77 | |
78 GtkTargetEntry selection_targets[] = { | |
79 { "text/html", 0, TARGET_HTML }, | |
80 { "UTF8_STRING", 0, TARGET_UTF8_STRING }, | |
81 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, | |
82 { "STRING", 0, TARGET_STRING }, | |
83 { "TEXT", 0, TARGET_TEXT}}; | |
84 | |
70 static GtkSmileyTree* | 85 static GtkSmileyTree* |
71 gtk_smiley_tree_new () | 86 gtk_smiley_tree_new () |
72 { | 87 { |
73 return g_new0 (GtkSmileyTree, 1); | 88 return g_new0 (GtkSmileyTree, 1); |
74 } | 89 } |
349 copy->text = g_strdup(text); | 364 copy->text = g_strdup(text); |
350 imhtml->copyables = g_slist_append(imhtml->copyables, copy); | 365 imhtml->copyables = g_slist_append(imhtml->copyables, copy); |
351 return copy; | 366 return copy; |
352 } | 367 } |
353 | 368 |
354 static void copy_clipboard_cb(GtkIMHtml *imhtml, GtkClipboard *clipboard) | 369 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { |
355 { | 370 GtkTextIter start, end; |
356 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); | 371 GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer); |
357 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 372 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); |
358 GtkTextIter start, end, smiley, last; | |
359 GString *str = g_string_new(NULL); | |
360 char *text; | |
361 | |
362 GSList *copyables; | |
363 | |
364 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); | 373 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel); |
365 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); | 374 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins); |
366 | 375 |
367 if (gtk_text_iter_equal(&start, &end)) | 376 char *text = gtk_imhtml_get_markup_range(imhtml, &start, &end); |
368 return; | 377 if (info == TARGET_HTML) { |
369 | 378 int len; |
370 gtk_text_iter_order(&start, &end); | 379 GString *str = g_string_new(NULL); |
371 last = start; | 380 |
372 | 381 /* Mozilla asks that we start our text/html with the Unicode byte order mark */ |
373 for (copyables = imhtml->copyables; copyables != NULL; copyables = copyables->next) { | 382 str = g_string_append_unichar(str, 0xfeff); |
374 GtkIMHtmlCopyable *copy = GTK_IMHTML_COPYABLE(copyables->data); | 383 str = g_string_append(str, text); |
375 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &smiley, copy->mark); | 384 char *selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
376 if (gtk_text_iter_compare(&end, &smiley) < 0) { | 385 gtk_selection_data_set (selection_data, gdk_atom_intern("text/html", FALSE), 16, selection, len); |
377 break; | 386 g_string_free(str, TRUE); |
378 } | 387 g_free(text); |
379 if (gtk_text_iter_compare(&last, &smiley) <= 0) { | 388 g_free(selection); |
380 text = gtk_text_buffer_get_text(imhtml->text_buffer, &last, &smiley, FALSE); | 389 } else { |
381 str = g_string_append(str, text); | 390 gtk_selection_data_set_text(selection_data, text, strlen(text)); |
382 str = g_string_append(str, copy->text); | 391 } |
383 last = smiley; | 392 } |
384 g_free(text); | 393 |
385 } | 394 static void gtk_imhtml_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml) |
386 } | 395 { |
387 text = gtk_text_buffer_get_text(imhtml->text_buffer, &last, &end, FALSE); | 396 } |
388 str = g_string_append(str, text); | 397 |
389 g_free(text); | 398 static void copy_clipboard_cb(GtkIMHtml *imhtml, GtkClipboard *clipboard) |
390 | 399 { |
391 if (!gtk_text_iter_equal(&start, &last)) | 400 gtk_clipboard_set_with_owner(clipboard ? clipboard : |
392 #ifdef _WIN32 | 401 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), |
393 gtk_clipboard_set_text(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), | 402 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), |
394 str->str, str->len); | 403 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, |
395 #endif | 404 (GtkClipboardClearFunc)gtk_imhtml_clipboard_clear, G_OBJECT(imhtml)); |
396 gtk_clipboard_set_text(clipboard ? clipboard : | 405 |
397 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), | 406 g_signal_stop_emission_by_name(imhtml, "copy-clipboard"); |
398 str->str, str->len); | |
399 | |
400 g_string_free(str, TRUE); | |
401 } | 407 } |
402 | 408 |
403 static gboolean button_release_cb(GtkIMHtml *imhtml, GdkEventButton event, gpointer the_foibles_of_man) | 409 static gboolean button_release_cb(GtkIMHtml *imhtml, GdkEventButton event, gpointer the_foibles_of_man) |
404 { | 410 { |
411 GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (imhtml), | |
412 GDK_SELECTION_PRIMARY); | |
413 gtk_text_buffer_remove_selection_clipboard (imhtml->text_buffer, clipboard); | |
405 copy_clipboard_cb(imhtml, gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); | 414 copy_clipboard_cb(imhtml, gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); |
406 return FALSE; | 415 return FALSE; |
407 } | 416 } |
408 #endif | 417 #endif |
409 | 418 |
536 imhtml->scalables = NULL; | 545 imhtml->scalables = NULL; |
537 #if GTK_CHECK_VERSION(2,2,0) | 546 #if GTK_CHECK_VERSION(2,2,0) |
538 imhtml->copyables = NULL; | 547 imhtml->copyables = NULL; |
539 #endif | 548 #endif |
540 gtk_imhtml_set_editable(imhtml, FALSE); | 549 gtk_imhtml_set_editable(imhtml, FALSE); |
550 | |
541 } | 551 } |
542 | 552 |
543 GtkWidget *gtk_imhtml_new(void *a, void *b) | 553 GtkWidget *gtk_imhtml_new(void *a, void *b) |
544 { | 554 { |
545 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); | 555 return GTK_WIDGET(g_object_new(gtk_imhtml_get_type(), NULL)); |
2277 | 2287 |
2278 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | 2288 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) |
2279 { | 2289 { |
2280 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2290 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); |
2281 GtkTextIter iter; | 2291 GtkTextIter iter; |
2282 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2283 GdkPixbuf *pixbuf = NULL; | 2292 GdkPixbuf *pixbuf = NULL; |
2284 GdkPixbufAnimation *annipixbuf = NULL; | 2293 GdkPixbufAnimation *annipixbuf = NULL; |
2285 GtkWidget *icon = NULL; | 2294 GtkWidget *icon = NULL; |
2286 | |
2287 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); | 2295 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); |
2296 | |
2297 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2288 g_object_set_data(G_OBJECT(anchor), "text_tag", smiley); | 2298 g_object_set_data(G_OBJECT(anchor), "text_tag", smiley); |
2299 | |
2289 annipixbuf = gtk_smiley_tree_image(imhtml, sml, smiley); | 2300 annipixbuf = gtk_smiley_tree_image(imhtml, sml, smiley); |
2290 if(annipixbuf) { | 2301 if(annipixbuf) { |
2291 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | 2302 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { |
2292 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); | 2303 pixbuf = gdk_pixbuf_animation_get_static_image(annipixbuf); |
2293 if(pixbuf) | 2304 if(pixbuf) |
2294 icon = gtk_image_new_from_pixbuf(pixbuf); | 2305 icon = gtk_image_new_from_pixbuf(pixbuf); |
2295 } else { | 2306 } else { |
2296 icon = gtk_image_new_from_animation(annipixbuf); | 2307 icon = gtk_image_new_from_animation(annipixbuf); |
2328 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | 2339 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else |
2329 * check the list of formatted strings, sorted by the position of the starting tags and apply them as | 2340 * check the list of formatted strings, sorted by the position of the starting tags and apply them as |
2330 * needed. After applying the start tags, add the end tags to the "closers" list, which is sorted by | 2341 * needed. After applying the start tags, add the end tags to the "closers" list, which is sorted by |
2331 * location of ending tags. These get applied in a similar fashion. Finally, replace <, >, &, and " | 2342 * location of ending tags. These get applied in a similar fashion. Finally, replace <, >, &, and " |
2332 * with their HTML equivilent. */ | 2343 * with their HTML equivilent. */ |
2333 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | 2344 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
2334 { | 2345 { |
2335 gunichar c; | 2346 gunichar c; |
2336 GtkIMHtmlFormatSpan *sspan = NULL, *espan = NULL; | 2347 GtkIMHtmlFormatSpan *sspan = NULL, *espan = NULL; |
2337 GtkTextIter iter, siter, eiter; | 2348 GtkTextIter iter, siter, eiter; |
2338 GList *starters = imhtml->format_spans; | 2349 GList *starters = imhtml->format_spans; |
2339 GList *closers = NULL;; | 2350 GList *closers = NULL; |
2340 GString *str = g_string_new(""); | 2351 GString *str = g_string_new(""); |
2341 g_list_sort_with_data(starters, (GCompareDataFunc)span_compare_begin, imhtml->text_buffer); | 2352 g_list_sort_with_data(starters, (GCompareDataFunc)span_compare_begin, imhtml->text_buffer); |
2342 | 2353 |
2343 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | 2354 gtk_text_iter_order(start, end); |
2355 iter = *start; | |
2356 | |
2344 | 2357 |
2345 /* Initialize these to the end iter */ | 2358 /* Initialize these to the end iter */ |
2346 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | 2359 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); |
2347 eiter = siter; | 2360 eiter = siter; |
2348 | 2361 |
2349 if (starters) { | 2362 if (starters) { |
2350 sspan = (GtkIMHtmlFormatSpan*)starters->data; | 2363 while (starters) { |
2351 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | 2364 GtkTextIter tagend; |
2352 } | 2365 sspan = (GtkIMHtmlFormatSpan*)starters->data; |
2353 | 2366 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); |
2354 while ((c = gtk_text_iter_get_char(&iter)) != 0) { | 2367 if (gtk_text_iter_compare(&siter, start) > 0) |
2368 break; | |
2369 if (sspan->end) | |
2370 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &tagend, sspan->end); | |
2371 if (sspan->end == NULL || gtk_text_iter_compare(&tagend, start) > 0) { | |
2372 str = g_string_append(str, sspan->start_tag); | |
2373 closers = g_list_append(closers, sspan); | |
2374 } | |
2375 sspan = (GtkIMHtmlFormatSpan*)starters->data; | |
2376 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | |
2377 starters = starters->next; | |
2378 } | |
2379 if (!starters) { | |
2380 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
2381 sspan = NULL; | |
2382 } | |
2383 } | |
2384 | |
2385 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
2355 if (c == 0xFFFC) { | 2386 if (c == 0xFFFC) { |
2356 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | 2387 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); |
2357 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); | 2388 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); |
2358 str = g_string_append(str, text); | 2389 str = g_string_append(str, text); |
2359 } else { | 2390 } else { |
2404 gtk_text_iter_forward_char(&iter); | 2435 gtk_text_iter_forward_char(&iter); |
2405 } | 2436 } |
2406 return g_string_free(str, FALSE); | 2437 return g_string_free(str, FALSE); |
2407 } | 2438 } |
2408 | 2439 |
2440 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | |
2441 { | |
2442 GtkTextIter start, end; | |
2443 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
2444 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
2445 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
2446 } | |
2447 | |
2409 char *gtk_imhtml_get_text(GtkIMHtml *imhtml) | 2448 char *gtk_imhtml_get_text(GtkIMHtml *imhtml) |
2410 { | 2449 { |
2411 GtkTextIter start_iter, end_iter; | 2450 GtkTextIter start_iter, end_iter; |
2412 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start_iter); | 2451 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start_iter); |
2413 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end_iter); | 2452 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end_iter); |