* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
#include "gtksignal.h"
+#include "gtkmarshalers.h"
#include "gtktextlayout.h"
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
#include <stdlib.h>
#include <string.h>
-static GtkTextLineData *gtk_text_line_data_new (GtkTextLayout *layout,
- GtkTextLine *line);
-
static GtkTextLineData *gtk_text_layout_real_wrap (GtkTextLayout *layout,
GtkTextLine *line,
/* may be NULL */
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextLayoutClass, invalidated),
NULL, NULL,
- gtk_marshal_VOID__VOID,
+ _gtk_marshal_VOID__VOID,
GTK_TYPE_NONE,
0);
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextLayoutClass, changed),
NULL, NULL,
- gtk_marshal_VOID__INT_INT_INT,
+ _gtk_marshal_VOID__INT_INT_INT,
GTK_TYPE_NONE,
3,
GTK_TYPE_INT,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextLayoutClass, allocate_child),
NULL, NULL,
- gtk_marshal_VOID__OBJECT_INT_INT,
+ _gtk_marshal_VOID__OBJECT_INT_INT,
GTK_TYPE_NONE,
3,
GTK_TYPE_OBJECT,
GTK_TYPE_INT);
}
-void
+static void
gtk_text_layout_init (GtkTextLayout *text_layout)
{
text_layout->cursor_visible = TRUE;
{
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
+ DV (g_print ("invalidating all due to default style change (%s)\n", G_STRLOC));
gtk_text_layout_invalidate_all (layout);
}
layout->rtl_context = rtl_context;
g_object_ref (G_OBJECT (rtl_context));
+ DV (g_print ("invalidating all due to new pango contexts (%s)\n", G_STRLOC));
gtk_text_layout_invalidate_all (layout);
}
layout->screen_width = width;
+ DV (g_print ("invalidating all due to new screen width (%s)\n", G_STRLOC));
gtk_text_layout_invalidate_all (layout);
}
/* -1 since bottom_y is one past */
last_btree_line =
_gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer),
- layout, bottom_y - 1, NULL);
+ layout, bottom_y - 1, NULL);
if (!last_btree_line)
last_btree_line =
- _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
- _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1,
- NULL);
+ _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
g_assert (last_btree_line != NULL);
if (line == last_btree_line)
break;
- line = _gtk_text_line_next (line);
+ line = _gtk_text_line_next_excluding_last (line);
}
retval = g_slist_reverse (retval);
if (line == last_line)
break;
- line = _gtk_text_line_next (line);
+ line = _gtk_text_line_next_excluding_last (line);
}
gtk_text_layout_invalidated (layout);
*
* Check if there are any invalid regions in a #GtkTextLayout's buffer
*
- * Return value: #TRUE if any invalid regions were found
+ * Return value: %TRUE if any invalid regions were found
**/
gboolean
gtk_text_layout_is_valid (GtkTextLayout *layout)
}
seen += line_data->height;
- line = _gtk_text_line_next (line);
+ line = _gtk_text_line_next_excluding_last (line);
}
/* If we found and validated any invalid lines, update size and
GtkTextLineDisplay *display;
g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), NULL);
-
+ g_return_val_if_fail (line != NULL, NULL);
+
if (line_data == NULL)
{
- line_data = gtk_text_line_data_new (layout, line);
+ line_data = _gtk_text_line_data_new (layout, line);
_gtk_text_line_add_data (line, line_data);
}
static void
set_para_values (GtkTextLayout *layout,
GtkTextAttributes *style,
- GtkTextLineDisplay *display,
- gdouble *align)
+ GtkTextLineDisplay *display)
{
PangoAlignment pango_align = PANGO_ALIGN_LEFT;
int layout_width;
break;
}
- switch (pango_align)
- {
- case PANGO_ALIGN_LEFT:
- *align = 0.0;
- break;
- case PANGO_ALIGN_RIGHT:
- *align = 1.0;
- break;
- case PANGO_ALIGN_CENTER:
- *align = 0.5;
- break;
- }
-
pango_layout_set_alignment (display->layout, pango_align);
pango_layout_set_spacing (display->layout,
style->pixels_inside_wrap * PANGO_SCALE);
{
PangoAttribute *attr;
- attr = pango_attr_font_desc_new (&style->font);
+ attr = pango_attr_font_desc_new (style->font);
attr->start_index = start;
attr->end_index = start + byte_count;
cursor->y = PANGO_PIXELS (strong_pos.y);
cursor->height = PANGO_PIXELS (strong_pos.height);
cursor->is_strong = TRUE;
- cursor->is_weak = FALSE;
+ cursor->is_weak = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
display->cursors = g_slist_prepend (display->cursors, cursor);
}
cursor->x = PANGO_PIXELS (weak_pos.x);
cursor->y = PANGO_PIXELS (weak_pos.y);
cursor->height = PANGO_PIXELS (weak_pos.height);
- cursor->is_strong = FALSE;
+ cursor->is_strong = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
cursor->is_weak = TRUE;
display->cursors = g_slist_prepend (display->cursors, cursor);
}
do
{
GtkTextAppearance appearance = style->appearance;
- PangoFontDescription font_desc;
+ PangoFontDescription *font_desc = pango_font_description_copy_static (style->font);
PangoAttribute *insert_attr;
GSList *extra_attrs = NULL;
GSList *tmp_list;
if (end == G_MAXINT)
end = layout->preedit_len;
- pango_attr_iterator_get_font (iter, &style->font,
- &font_desc, &language, &extra_attrs);
+ pango_attr_iterator_get_font (iter, font_desc, &language, &extra_attrs);
tmp_list = extra_attrs;
while (tmp_list)
g_slist_free (extra_attrs);
- insert_attr = pango_attr_font_desc_new (&font_desc);
+ insert_attr = pango_attr_font_desc_new (font_desc);
insert_attr->start_index = start + offset;
insert_attr->end_index = end + offset;
add_generic_attrs (layout, &appearance, end - start,
attrs, start + offset,
size_only, TRUE);
+
+ pango_font_description_free (font_desc);
}
while (pango_attr_iterator_next (iter));
gchar *text;
PangoAttrList *attrs;
gint text_allocated, layout_byte_offset, buffer_byte_offset;
- gdouble align;
PangoRectangle extents;
gboolean para_values_set = FALSE;
GSList *cursor_byte_offsets = NULL;
*/
if (!para_values_set)
{
- set_para_values (layout, style, display, &align);
+ set_para_values (layout, style, display);
para_values_set = TRUE;
}
if (!para_values_set)
{
style = get_style (layout, &iter);
- set_para_values (layout, style, display, &align);
+ set_para_values (layout, style, display);
release_style (layout, style);
}
pango_layout_get_extents (display->layout, NULL, &extents);
- display->x_offset += (display->total_width - PANGO_PIXELS (extents.x + extents.width)) * align;
-
display->width = PANGO_PIXELS (extents.width) + display->left_margin + display->right_margin;
display->height += PANGO_PIXELS (extents.height);
gint index,
gint trailing)
{
+ g_return_if_fail (!_gtk_text_line_is_last (display->line,
+ _gtk_text_buffer_get_btree (layout->buffer)));
+
if (index >= display->insert_index + layout->preedit_len)
index -= layout->preedit_len;
else if (index > display->insert_index)
gtk_text_iter_forward_chars (iter, trailing);
}
-/* FIXME: This really doesn't belong in this file ... */
-static GtkTextLineData*
-gtk_text_line_data_new (GtkTextLayout *layout,
- GtkTextLine *line)
-{
- GtkTextLineData *line_data;
-
- line_data = g_new (GtkTextLineData, 1);
-
- line_data->view_id = layout;
- line_data->next = NULL;
- line_data->width = 0;
- line_data->height = 0;
- line_data->valid = FALSE;
-
- return line_data;
-}
-
static void
get_line_at_y (GtkTextLayout *layout,
gint y,
layout, y, line_top);
if (*line == NULL)
{
- *line = _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
- _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL);
+ *line = _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+
if (line_top)
*line_top =
_gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer),
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
g_return_if_fail (target_iter != NULL);
- /* Adjust pixels to be on-screen. This gives nice
- behavior if the user is dragging with a pointer grab.
- */
- if (x < 0)
- x = 0;
- if (x > layout->width)
- x = layout->width;
-
get_line_at_y (layout, y, &line, &line_top);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
x -= display->x_offset;
y -= line_top + display->top_margin;
- /* We clamp y to the area of the actual layout so that the layouts
- * hit testing works OK on the space above and below the layout
+ /* If we are below the layout, position the cursor at the last character
+ * of the line.
*/
- y = CLAMP (y, 0, display->height - display->top_margin - display->bottom_margin - 1);
-
- if (!pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE,
- &byte_index, &trailing))
+ if (y > display->height - display->top_margin - display->bottom_margin)
{
byte_index = _gtk_text_line_byte_count (line);
trailing = 0;
}
+ else
+ {
+ /* Ignore the "outside" return value from pango. Pango is doing
+ * the right thing even if we are outside the layout in the
+ * x-direction.
+ */
+ pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE,
+ &byte_index, &trailing);
+ }
line_display_index_to_iter (layout, display, target_iter, byte_index, trailing);
}
}
+/**
+ * _gtk_text_layout_get_line_xrange:
+ * @layout: a #GtkTextLayout
+ * @iter: a #GtkTextIter
+ * @x: location to store the top of the paragraph in pixels,
+ * or %NULL.
+ * @width location to store the height of the paragraph in pixels,
+ * or %NULL.
+ *
+ * Find the range of X coordinates for the paragraph containing
+ * the given iter. Private for 2.0 due to API freeze, could
+ * be made public for 2.2.
+ **/
+void
+_gtk_text_layout_get_line_xrange (GtkTextLayout *layout,
+ const GtkTextIter *iter,
+ gint *x,
+ gint *width)
+{
+ GtkTextLine *line;
+
+ g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
+ g_return_if_fail (_gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer));
+
+ line = _gtk_text_iter_get_text_line (iter);
+
+ if (x)
+ *x = 0; /* FIXME This is wrong; should represent the first available cursor position */
+
+ if (width)
+ {
+ GtkTextLineData *line_data = _gtk_text_line_get_data (line, layout);
+ if (line_data)
+ *width = line_data->width;
+ else
+ *width = 0;
+ }
+}
+
void
gtk_text_layout_get_iter_location (GtkTextLayout *layout,
const GtkTextIter *iter,
if (!line)
{
line =
- _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
- _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1,
- NULL);
+ _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+
line_top =
_gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer),
line, layout);
line_top += display->bottom_margin;
gtk_text_layout_free_line_display (layout, display);
- next = _gtk_text_line_next (line);
+ next = _gtk_text_line_next_excluding_last (line);
if (!next)
found_line = line;
line = _gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), layout, y, &line_top);
if (!line)
{
- line = _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
- _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL);
+ line = _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+
line_top = _gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), line, layout);
}
if (tmp_top < y)
{
found_line = line;
+ pango_layout_iter_free (layout_iter);
goto done;
}
}
gtk_text_layout_free_line_display (layout, display);
- line = _gtk_text_line_next (line);
+ line = _gtk_text_line_next_excluding_last (line);
}
return
}
else if (new_index > byte_count)
{
- line = _gtk_text_line_next (line);
+ line = _gtk_text_line_next_excluding_last (line);
if (!line)
goto done;