* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
#include "gtktextdisplay.h"
/* DO NOT go putting private headers in here. This file should only
* use the semi-public headers, as with gtktextview.c.
gtk_text_render_state_update (GtkTextRenderState *state,
GtkTextAppearance *new_appearance)
{
+ GdkScreen *screen = gtk_widget_get_screen (state->widget);
+
if (!state->last_appearance ||
!gdk_color_equal (&new_appearance->fg_color, &state->last_appearance->fg_color))
gtk_text_render_state_set_color (state, state->fg_gc, &new_appearance->fg_color);
{
if (new_appearance->fg_stipple)
{
- gdk_gc_set_fill (state->fg_gc, GDK_STIPPLED);
- gdk_gc_set_stipple (state->fg_gc, new_appearance->fg_stipple);
+ if (screen == gdk_drawable_get_screen (new_appearance->fg_stipple))
+ {
+ gdk_gc_set_fill (state->fg_gc, GDK_STIPPLED);
+ gdk_gc_set_stipple (state->fg_gc, new_appearance->fg_stipple);
+ }
+ else
+ g_warning ("gtk_text_render_state_update:\n"
+ "The foreground stipple bitmap has been created on the wrong screen.\n"
+ "Ignoring the stipple bitmap information.");
}
else
{
{
if (new_appearance->bg_stipple)
{
- gdk_gc_set_fill (state->bg_gc, GDK_STIPPLED);
- gdk_gc_set_stipple (state->bg_gc, new_appearance->bg_stipple);
+ if (screen == gdk_drawable_get_screen (new_appearance->bg_stipple))
+ {
+ gdk_gc_set_fill (state->bg_gc, GDK_STIPPLED);
+ gdk_gc_set_stipple (state->bg_gc, new_appearance->bg_stipple);
+ }
+ else
+ g_warning ("gtk_text_render_state_update:\n"
+ "The background stipple bitmap has been created on the wrong screen.\n"
+ "Ignoring the stipple bitmap information.");
+
}
else
{
GSList **shaped_pointer,
int x,
int y,
- gboolean selected)
+ gboolean selected,
+ GList **widgets)
{
GSList *tmp_list = line->runs;
PangoRectangle overall_rect;
if (selected)
{
- fg_gc = render_state->widget->style->text_gc[GTK_STATE_SELECTED];
+ if (GTK_WIDGET_HAS_FOCUS (render_state->widget))
+ fg_gc = render_state->widget->style->text_gc[GTK_STATE_SELECTED];
+ else
+ fg_gc = render_state->widget->style->text_gc [GTK_STATE_ACTIVE];
}
else
{
GObject *shaped = (*shaped_pointer)->data;
*shaped_pointer = (*shaped_pointer)->next;
-
- if (GDK_IS_PIXBUF (shaped))
+
+ if (shaped == NULL)
+ {
+ /* This happens if we have an empty widget anchor. Draw
+ * something empty-looking.
+ */
+ GdkRectangle shape_rect, draw_rect;
+
+ shape_rect.x = x + x_off / PANGO_SCALE;
+ shape_rect.y = risen_y - PANGO_PIXELS (logical_rect.height);
+ shape_rect.width = PANGO_PIXELS (logical_rect.width);
+ shape_rect.height = PANGO_PIXELS (logical_rect.height);
+
+ if (gdk_rectangle_intersect (&shape_rect, &render_state->clip_rect,
+ &draw_rect))
+ {
+ gdk_draw_rectangle (drawable, render_state->fg_gc,
+ FALSE, shape_rect.x, shape_rect.y,
+ shape_rect.width, shape_rect.height);
+
+ gdk_draw_line (drawable, render_state->fg_gc,
+ shape_rect.x, shape_rect.y,
+ shape_rect.x + shape_rect.width,
+ shape_rect.y + shape_rect.height);
+
+ gdk_draw_line (drawable, render_state->fg_gc,
+ shape_rect.x + shape_rect.width, shape_rect.y,
+ shape_rect.x,
+ shape_rect.y + shape_rect.height);
+ }
+
+ shaped_width_pixels = shape_rect.width;
+ }
+ else if (GDK_IS_PIXBUF (shaped))
{
gint width, height;
GdkRectangle pixbuf_rect, draw_rect;
}
else if (GTK_IS_WIDGET (shaped))
{
- gint width, height;
- GdkRectangle draw_rect;
GtkWidget *widget;
widget = GTK_WIDGET (shaped);
- width = widget->allocation.width;
- height = widget->allocation.height;
-
- g_print ("widget allocation at %d,%d %d x %d\n",
- widget->allocation.x,
- widget->allocation.y,
- widget->allocation.width,
- widget->allocation.height);
-
- if (GTK_WIDGET_DRAWABLE (widget) &&
- gdk_rectangle_intersect (&widget->allocation,
- &render_state->clip_rect,
- &draw_rect))
+ shaped_width_pixels = widget->allocation.width;
+ if (widgets)
{
- g_print ("drawing widget area %d,%d %d x %d\n",
- draw_rect.x,
- draw_rect.y,
- draw_rect.width,
- draw_rect.height);
-
- gtk_widget_draw (widget, &draw_rect);
+ g_object_ref (G_OBJECT (widget));
+ *widgets = g_list_prepend (*widgets, widget);
}
-
- shaped_width_pixels = width;
}
else
g_assert_not_reached (); /* not a pixbuf or widget */
int x,
int y,
int selection_start_index,
- int selection_end_index)
+ int selection_end_index,
+ GList **widgets)
{
GSList *shaped_pointer = line_display->shaped_objects;
PangoLayout *layout = line_display->layout;
PangoLayoutIter *iter;
PangoRectangle layout_logical;
int screen_width;
+ GdkGC *fg_gc, *bg_gc;
+ gint state;
gboolean first = TRUE;
screen_width = line_display->total_width;
+ if (GTK_WIDGET_HAS_FOCUS (render_state->widget))
+ state = GTK_STATE_SELECTED;
+ else
+ state = GTK_STATE_ACTIVE;
+
+ fg_gc = render_state->widget->style->text_gc [state];
+ bg_gc = render_state->widget->style->base_gc [state];
+
do
{
PangoLayoutLine *line = pango_layout_iter_get_line (iter);
selection_end_index > line->length + byte_offset) /* All selected */
{
gdk_draw_rectangle (drawable,
- render_state->widget->style->base_gc[GTK_STATE_SELECTED],
+ bg_gc,
TRUE,
x + line_display->left_margin,
selection_y,
render_layout_line (drawable, render_state, line, &shaped_pointer,
x + PANGO_PIXELS (line_rect.x),
y + PANGO_PIXELS (baseline),
- TRUE);
+ TRUE,
+ widgets);
}
else
{
line, &shaped_pointer,
x + PANGO_PIXELS (line_rect.x),
y + PANGO_PIXELS (baseline),
- FALSE);
+ FALSE,
+ widgets);
- if (selection_start_index < byte_offset + line->length &&
+ if (selection_start_index <= byte_offset + line->length &&
selection_end_index > byte_offset) /* Some selected */
{
GdkRegion *clip_region = get_selected_clip (render_state, layout, line,
selection_y,
selection_height,
selection_start_index, selection_end_index);
-
- gdk_gc_set_clip_region (render_state->widget->style->text_gc [GTK_STATE_SELECTED], clip_region);
- gdk_gc_set_clip_region (render_state->widget->style->base_gc [GTK_STATE_SELECTED], clip_region);
+ gdk_gc_set_clip_region (fg_gc, clip_region);
+ gdk_gc_set_clip_region (bg_gc, clip_region);
gdk_draw_rectangle (drawable,
- render_state->widget->style->base_gc[GTK_STATE_SELECTED],
+ bg_gc,
TRUE,
x + PANGO_PIXELS (line_rect.x),
selection_y,
render_layout_line (drawable, render_state, line, &shaped_pointer_tmp,
x + PANGO_PIXELS (line_rect.x),
y + PANGO_PIXELS (baseline),
- TRUE);
+ TRUE,
+ widgets);
- gdk_gc_set_clip_region (render_state->widget->style->text_gc [GTK_STATE_SELECTED], NULL);
- gdk_gc_set_clip_region (render_state->widget->style->base_gc [GTK_STATE_SELECTED], NULL);
+ gdk_gc_set_clip_region (fg_gc, NULL);
+ gdk_gc_set_clip_region (bg_gc, NULL);
gdk_region_destroy (clip_region);
(line_display->direction == GTK_TEXT_DIR_RTL && selection_end_index > byte_offset + line->length)))
{
gdk_draw_rectangle (drawable,
- render_state->widget->style->base_gc[GTK_STATE_SELECTED],
+ bg_gc,
TRUE,
x + line_display->left_margin,
selection_y,
PANGO_PIXELS (line_rect.x) - PANGO_PIXELS (line_rect.width);
gdk_draw_rectangle (drawable,
- render_state->widget->style->base_gc[GTK_STATE_SELECTED],
+ bg_gc,
TRUE,
x + PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width),
selection_y,
gtk_text_layout_draw (GtkTextLayout *layout,
GtkWidget *widget,
GdkDrawable *drawable,
+ GdkGC *cursor_gc,
/* Location of the drawable
in layout coordinates */
gint x_offset,
gint x,
gint y,
gint width,
- gint height)
+ gint height,
+ /* widgets to expose */
+ GList **widgets)
{
GdkRectangle clip;
gint current_y;
GtkTextLineDisplay *line_display;
gint selection_start_index = -1;
gint selection_end_index = -1;
+ gboolean have_strong;
+ gboolean have_weak;
GtkTextLine *line = tmp_list->data;
{
GtkTextIter line_start, line_end;
gint byte_count;
-
+
gtk_text_layout_get_iter_at_line (layout,
&line_start,
line, 0);
- byte_count = gtk_text_iter_get_bytes_in_line (&line_start);
-
- /* FIXME the -1 assumes a newline I think */
- gtk_text_layout_get_iter_at_line (layout,
- &line_end,
- line, byte_count - 1);
+ line_end = line_start;
+ gtk_text_iter_forward_to_line_end (&line_end);
+ byte_count = gtk_text_iter_get_line_index (&line_end);
- if (gtk_text_iter_compare (&selection_start, &line_end) < 0 &&
- gtk_text_iter_compare (&selection_end, &line_start) > 0)
+ if (gtk_text_iter_compare (&selection_start, &line_end) <= 0 &&
+ gtk_text_iter_compare (&selection_end, &line_start) >= 0)
{
if (gtk_text_iter_compare (&selection_start, &line_start) >= 0)
selection_start_index = gtk_text_iter_get_line_index (&selection_start);
render_para (drawable, render_state, line_display,
- x_offset,
current_y,
- selection_start_index, selection_end_index);
-
+ selection_start_index, selection_end_index,
+ widgets);
/* We paint the cursors last, because they overlap another chunk
and need to appear on top. */
+ have_strong = FALSE;
+ have_weak = FALSE;
+
+ cursor_list = line_display->cursors;
+ while (cursor_list)
+ {
+ GtkTextCursorDisplay *cursor = cursor_list->data;
+ if (cursor->is_strong)
+ have_strong = TRUE;
+ else
+ have_weak = TRUE;
+
+ cursor_list = cursor_list->next;
+ }
+
cursor_list = line_display->cursors;
while (cursor_list)
{
GtkTextCursorDisplay *cursor = cursor_list->data;
+ GtkTextDirection dir;
+ GdkRectangle cursor_location;
GdkGC *gc;
- if (cursor->is_strong)
- gc = widget->style->base_gc[GTK_STATE_SELECTED];
- else
- gc = widget->style->text_gc[GTK_STATE_NORMAL];
-
- gdk_gc_set_clip_rectangle(gc, &clip);
- gdk_draw_line (drawable, gc,
- line_display->x_offset + cursor->x - x_offset,
- current_y + line_display->top_margin + cursor->y,
- line_display->x_offset + cursor->x - x_offset,
- current_y + line_display->top_margin + cursor->y + cursor->height - 1);
- gdk_gc_set_clip_rectangle(gc, NULL);
+ dir = line_display->direction;
+ if (have_strong && have_weak)
+ {
+ if (!cursor->is_strong)
+ dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+ }
+
+ cursor_location.x = line_display->x_offset + cursor->x - x_offset;
+ cursor_location.y = current_y + line_display->top_margin + cursor->y;
+ cursor_location.width = 0;
+ cursor_location.height = cursor->height;
+
+ gc = _gtk_get_insertion_cursor_gc (widget, cursor->is_strong);
+ gdk_gc_set_clip_rectangle(gc, &clip);
+ _gtk_draw_insertion_cursor (widget, drawable, gc, &cursor_location,
+ dir, have_strong && have_weak);
+ gdk_gc_set_clip_rectangle (gc, NULL);
+
+ g_object_unref (gc);
cursor_list = cursor_list->next;
}