| 2421 { |
2421 { |
| 2422 GtkIMHtmlProtocol *proto = imhtml_find_protocol(text, FALSE); |
2422 GtkIMHtmlProtocol *proto = imhtml_find_protocol(text, FALSE); |
| 2423 return proto ? proto->length : 0; |
2423 return proto ? proto->length : 0; |
| 2424 } |
2424 } |
| 2425 |
2425 |
| |
2426 static gboolean smooth_scroll_cb(gpointer data); |
| |
2427 |
| 2426 /* |
2428 /* |
| 2427 <KingAnt> marv: The two IM image functions in oscar are purple_odc_send_im and purple_odc_incoming |
2429 <KingAnt> marv: The two IM image functions in oscar are purple_odc_send_im and purple_odc_incoming |
| 2428 |
2430 |
| 2429 |
2431 |
| 2430 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) |
2432 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) |
| 2475 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
2477 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
| 2476 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); |
2478 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); |
| 2477 |
2479 |
| 2478 if (((y + height) - (rect.y + rect.height)) > height && |
2480 if (((y + height) - (rect.y + rect.height)) > height && |
| 2479 gtk_text_buffer_get_char_count(imhtml->text_buffer)) { |
2481 gtk_text_buffer_get_char_count(imhtml->text_buffer)) { |
| 2480 options |= GTK_IMHTML_NO_SCROLL; |
2482 /* If we are in the middle of smooth-scrolling, then take a scroll step. |
| |
2483 * If we are not in the middle of smooth-scrolling, that means we were |
| |
2484 * not looking at the end of the buffer before the new text was added, |
| |
2485 * so do not scroll. */ |
| |
2486 if (imhtml->scroll_time) |
| |
2487 smooth_scroll_cb(imhtml); |
| |
2488 else |
| |
2489 options |= GTK_IMHTML_NO_SCROLL; |
| 2481 } |
2490 } |
| 2482 } |
2491 } |
| 2483 |
2492 |
| 2484 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); |
2493 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); |
| 2485 |
2494 |
| 2504 /* |
2513 /* |
| 2505 * Smoothly scroll a GtkIMHtml. |
2514 * Smoothly scroll a GtkIMHtml. |
| 2506 * |
2515 * |
| 2507 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. |
2516 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. |
| 2508 */ |
2517 */ |
| 2509 static gboolean scroll_cb(gpointer data) |
2518 static gboolean smooth_scroll_cb(gpointer data) |
| 2510 { |
2519 { |
| 2511 GtkIMHtml *imhtml = data; |
2520 GtkIMHtml *imhtml = data; |
| 2512 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; |
2521 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; |
| 2513 gdouble max_val = adj->upper - adj->page_size; |
2522 gdouble max_val = adj->upper - adj->page_size; |
| 2514 gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); |
2523 gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); |
| 2518 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) { |
2527 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) { |
| 2519 /* time's up. jump to the end and kill the timer */ |
2528 /* time's up. jump to the end and kill the timer */ |
| 2520 gtk_adjustment_set_value(adj, max_val); |
2529 gtk_adjustment_set_value(adj, max_val); |
| 2521 g_timer_destroy(imhtml->scroll_time); |
2530 g_timer_destroy(imhtml->scroll_time); |
| 2522 imhtml->scroll_time = NULL; |
2531 imhtml->scroll_time = NULL; |
| |
2532 g_source_remove(imhtml->scroll_src); |
| |
2533 imhtml->scroll_src = 0; |
| 2523 return FALSE; |
2534 return FALSE; |
| 2524 } |
2535 } |
| 2525 |
2536 |
| 2526 /* scroll by 1/3rd the remaining distance */ |
2537 /* scroll by 1/3rd the remaining distance */ |
| 2527 gtk_adjustment_set_value(adj, scroll_val); |
2538 gtk_adjustment_set_value(adj, scroll_val); |
| 2528 return TRUE; |
2539 return TRUE; |
| 2529 } |
|
| 2530 |
|
| 2531 static gboolean smooth_scroll_idle_cb(gpointer data) |
|
| 2532 { |
|
| 2533 GtkIMHtml *imhtml = data; |
|
| 2534 imhtml->scroll_src = g_timeout_add(SCROLL_DELAY, scroll_cb, imhtml); |
|
| 2535 return FALSE; |
|
| 2536 } |
2540 } |
| 2537 |
2541 |
| 2538 static gboolean scroll_idle_cb(gpointer data) |
2542 static gboolean scroll_idle_cb(gpointer data) |
| 2539 { |
2543 { |
| 2540 GtkIMHtml *imhtml = data; |
2544 GtkIMHtml *imhtml = data; |
| 2552 g_timer_destroy(imhtml->scroll_time); |
2556 g_timer_destroy(imhtml->scroll_time); |
| 2553 if (imhtml->scroll_src) |
2557 if (imhtml->scroll_src) |
| 2554 g_source_remove(imhtml->scroll_src); |
2558 g_source_remove(imhtml->scroll_src); |
| 2555 if(smooth) { |
2559 if(smooth) { |
| 2556 imhtml->scroll_time = g_timer_new(); |
2560 imhtml->scroll_time = g_timer_new(); |
| 2557 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, smooth_scroll_idle_cb, imhtml, NULL); |
2561 imhtml->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, imhtml, NULL); |
| 2558 } else { |
2562 } else { |
| 2559 imhtml->scroll_time = NULL; |
2563 imhtml->scroll_time = NULL; |
| 2560 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); |
2564 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); |
| 2561 } |
2565 } |
| 2562 } |
2566 } |