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);