/gtkhtml-4.4.0/gtkhtml/htmltextslave.c
# · C · 1649 lines · 1247 code · 289 blank · 113 comment · 262 complexity · d6983973f832dd0bfaaf4f6aa115ef54 MD5 · raw file
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
- /* This file is part of the GtkHTML library.
- *
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- * Copyright (C) 1997 Torben Weis (weis@kde.org)
- * Copyright (C) 1999 Helix Code, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
- #include <config.h>
- #include <stdio.h>
- #include <string.h>
- #include "htmltextslave.h"
- #include "htmlclue.h"
- #include "htmlclueflow.h"
- #include "htmlcursor.h"
- #include "htmlcolor.h"
- #include "htmlcolorset.h"
- #include "htmlpainter.h"
- #include "htmlobject.h"
- #include "htmlprinter.h"
- #include "htmlplainpainter.h"
- #include "htmlgdkpainter.h"
- #include "htmlsettings.h"
- #include "gtkhtml.h"
- /* #define HTML_TEXT_SLAVE_DEBUG */
- HTMLTextSlaveClass html_text_slave_class;
- static HTMLObjectClass *parent_class = NULL;
- static void clear_glyph_items (HTMLTextSlave *slave);
- gchar *
- html_text_slave_get_text (HTMLTextSlave *slave)
- {
- if (!slave->charStart)
- slave->charStart = html_text_get_text (slave->owner, slave->posStart);
- return slave->charStart;
- }
- /* Split this TextSlave at the specified offset. */
- static void
- split (HTMLTextSlave *slave,
- guint offset,
- gint skip,
- gchar *start_pointer)
- {
- HTMLObject *obj;
- HTMLObject *new;
- g_return_if_fail (offset < slave->posLen);
- obj = HTML_OBJECT (slave);
- new = html_text_slave_new (slave->owner,
- slave->posStart + offset + skip,
- slave->posLen - (offset + skip));
- HTML_TEXT_SLAVE (new)->charStart = start_pointer;
- html_clue_append_after (HTML_CLUE (obj->parent), new, obj);
- slave->posLen = offset;
- }
- /* HTMLObject methods. */
- static void
- copy (HTMLObject *self,
- HTMLObject *dest)
- {
- (* HTML_OBJECT_CLASS (parent_class)->copy) (self, dest);
- /* FIXME it does not make much sense to me to share the owner. */
- HTML_TEXT_SLAVE (dest)->owner = HTML_TEXT_SLAVE (self)->owner;
- HTML_TEXT_SLAVE (dest)->posStart = HTML_TEXT_SLAVE (self)->posStart;
- HTML_TEXT_SLAVE (dest)->posLen = HTML_TEXT_SLAVE (self)->posLen;
- HTML_TEXT_SLAVE (dest)->glyph_items = NULL;
- }
- static inline gint
- html_text_slave_get_start_byte_offset (HTMLTextSlave *slave)
- {
- return html_text_slave_get_text (slave) - slave->owner->text;
- }
- static void
- hts_update_asc_dsc (HTMLPainter *painter,
- PangoItem *item,
- gint *asc,
- gint *dsc)
- {
- PangoFontMetrics *pfm;
- pfm = pango_font_get_metrics (item->analysis.font, item->analysis.language);
- if (asc)
- *asc = MAX (*asc, pango_font_metrics_get_ascent (pfm));
- if (dsc)
- *dsc = MAX (*dsc, pango_font_metrics_get_descent (pfm));
- pango_font_metrics_unref (pfm);
- }
- static gint
- hts_calc_width (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint *asc,
- gint *dsc)
- {
- /*HTMLText *text = slave->owner;
- gint line_offset, tabs = 0, width = 0;
- *
- line_offset = html_text_slave_get_line_offset (slave, 0, painter);
- if (line_offset != -1)
- width += (html_text_text_line_length (html_text_slave_get_text (slave), &line_offset, slave->posLen, &tabs) - slave->posLen)*
- html_painter_get_space_width (painter, html_text_get_font_style (text), text->face);
- *
- width += html_text_calc_part_width (text, painter, html_text_slave_get_text (slave), slave->posStart, slave->posLen, asc, dsc); */
- GSList *cur, *gilist = html_text_slave_get_glyph_items (slave, painter);
- PangoLanguage *language = NULL;
- PangoFont *font = NULL;
- gint width = 0;
- if (asc)
- *asc = html_painter_engine_to_pango (painter,
- html_painter_get_space_asc (painter, html_text_get_font_style (slave->owner), slave->owner->face));
- if (dsc)
- *dsc = html_painter_engine_to_pango (painter,
- html_painter_get_space_dsc (painter, html_text_get_font_style (slave->owner), slave->owner->face));
- for (cur = gilist; cur; cur = cur->next) {
- HTMLTextSlaveGlyphItem *sgi = (HTMLTextSlaveGlyphItem *) cur->data;
- PangoRectangle log_rect;
- PangoItem *item = sgi->glyph_item.item;
- pango_glyph_string_extents (sgi->glyph_item.glyphs, sgi->glyph_item.item->analysis.font, NULL, &log_rect);
- width += log_rect.width;
- if (item->analysis.font != font || item->analysis.language != language)
- hts_update_asc_dsc (painter, item, asc, dsc);
- }
- if (asc)
- *asc = html_painter_pango_to_engine (painter, *asc);
- if (dsc)
- *dsc = html_painter_pango_to_engine (painter, *dsc);
- width = html_painter_pango_to_engine (painter, width);
- /* printf ("hts width: %d\n", width); */
- return width;
- }
- inline static void
- glyphs_destroy (GList *glyphs)
- {
- GList *l;
- for (l = glyphs; l; l = l->next->next)
- pango_glyph_string_free ((PangoGlyphString *) l->data);
- g_list_free (glyphs);
- }
- inline static void
- glyph_items_destroy (GSList *glyph_items)
- {
- GSList *l;
- for (l = glyph_items; l; l = l->next) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) l->data;
- if (gi->type == HTML_TEXT_SLAVE_GLYPH_ITEM_CREATED) {
- if (gi->glyph_item.item)
- pango_item_free (gi->glyph_item.item);
- if (gi->glyph_item.glyphs)
- pango_glyph_string_free (gi->glyph_item.glyphs);
- g_free (gi->widths);
- }
- g_free (gi);
- }
- g_slist_free (glyph_items);
- }
- static gboolean
- html_text_slave_real_calc_size (HTMLObject *self,
- HTMLPainter *painter,
- GList **changed_objs)
- {
- HTMLText *owner;
- HTMLTextSlave *slave;
- GtkHTMLFontStyle font_style;
- gint new_ascent, new_descent, new_width;
- gboolean changed;
- slave = HTML_TEXT_SLAVE (self);
- owner = HTML_TEXT (slave->owner);
- font_style = html_text_get_font_style (owner);
- new_width = MAX (1, hts_calc_width (slave, painter, &new_ascent, &new_descent));
- /* handle sub & super script */
- if (font_style & GTK_HTML_FONT_STYLE_SUBSCRIPT || font_style & GTK_HTML_FONT_STYLE_SUPERSCRIPT) {
- gint shift = (new_ascent + new_descent) >> 1;
- if (font_style & GTK_HTML_FONT_STYLE_SUBSCRIPT) {
- new_descent += shift;
- new_ascent -= shift;
- } else {
- new_descent -= shift;
- new_ascent += shift;
- }
- }
- changed = FALSE;
- if (new_ascent != self->ascent) {
- self->ascent = new_ascent;
- changed = TRUE;
- }
- if (new_descent != self->descent) {
- self->descent = new_descent;
- changed = TRUE;
- }
- if (new_width != self->width) {
- self->width = new_width;
- changed = TRUE;
- }
- return changed;
- }
- #ifdef HTML_TEXT_SLAVE_DEBUG
- static void
- debug_print (HTMLFitType rv,
- gchar *text,
- gint len)
- {
- gint i;
- printf ("Split text");
- switch (rv) {
- case HTML_FIT_PARTIAL:
- printf (" (Partial): `");
- break;
- case HTML_FIT_NONE:
- printf (" (NoFit): `");
- break;
- case HTML_FIT_COMPLETE:
- printf (" (Complete): `");
- break;
- }
- for (i = 0; i < len; i++)
- putchar (text[i]);
- printf ("'\n");
- }
- #endif
- gint
- html_text_slave_get_line_offset (HTMLTextSlave *slave,
- gint offset,
- HTMLPainter *p)
- {
- HTMLObject *head = HTML_OBJECT (slave->owner)->next;
- g_assert (HTML_IS_TEXT_SLAVE (head));
- if (!html_clueflow_tabs (HTML_CLUEFLOW (HTML_OBJECT (slave)->parent), p))
- return -1;
- if (head->y + head->descent - 1 < HTML_OBJECT (slave)->y - HTML_OBJECT (slave)->ascent) {
- HTMLObject *prev;
- HTMLTextSlave *bol;
- gint line_offset = 0;
- prev = html_object_prev (HTML_OBJECT (slave)->parent, HTML_OBJECT (slave));
- while (prev->y + prev->descent - 1 >= HTML_OBJECT (slave)->y - HTML_OBJECT (slave)->ascent)
- prev = html_object_prev (HTML_OBJECT (slave)->parent, HTML_OBJECT (prev));
- bol = HTML_TEXT_SLAVE (prev->next);
- return html_text_text_line_length (html_text_slave_get_text (bol),
- &line_offset, slave->posStart + offset - bol->posStart, NULL);
- } else
- return html_text_get_line_offset (slave->owner, p, slave->posStart + offset);
- }
- static gboolean
- could_remove_leading_space (HTMLTextSlave *slave,
- gboolean lineBegin)
- {
- HTMLObject *o = HTML_OBJECT (slave->owner);
- if (lineBegin && (HTML_OBJECT (slave)->prev != o || o->prev))
- return TRUE;
- if (!o->prev)
- return FALSE;
- while (o->prev && HTML_OBJECT_TYPE (o->prev) == HTML_TYPE_CLUEALIGNED)
- o = o->prev;
- return o->prev ? FALSE : TRUE;
- }
- gchar *
- html_text_slave_remove_leading_space (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gboolean lineBegin)
- {
- gchar *begin;
- begin = html_text_slave_get_text (slave);
- if (*begin == ' ' && could_remove_leading_space (slave, lineBegin)) {
- begin = g_utf8_next_char (begin);
- slave->charStart = begin;
- slave->posStart++;
- slave->posLen--;
- }
- return begin;
- }
- gint
- html_text_slave_get_nb_width (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gboolean lineBegin)
- {
- html_text_slave_remove_leading_space (slave, painter, lineBegin);
- return html_object_calc_min_width (HTML_OBJECT (slave), painter);
- }
- /*
- * offset: current position - gchar offset
- * s: current position - string pointer
- * ii: current position - index of item
- * io: current position - offset within item
- * line_offset:
- * w: width for current position
- * lwl: last-whitespacing-length (in characters)
- * lbw: last-break-width
- * lbo: last-break-offset (into text)
- * lbsp: last-break-string-pointer
- *
- * Checks to see if breaking the text at the given position would result in it fitting
- * into the remaining width. If so, updates the last-break information (lwl,lbw,lbo,lbsp).
- * We'll actually break the item at the last break position that still fits.
- */
- static gboolean
- update_lb (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint widthLeft,
- gint offset,
- gchar *s,
- gint ii,
- gint io,
- gint line_offset,
- gint w,
- gint *lwl,
- gint *lbw,
- gint *lbo,
- gchar **lbsp,
- gboolean *force_fit)
- {
- gint new_ltw, new_lwl, aw;
- new_ltw = html_text_tail_white_space (slave->owner, painter, offset, ii, io, &new_lwl, line_offset, s);
- aw = w - new_ltw;
- if (aw <= widthLeft || *force_fit) {
- *lwl = new_lwl;
- *lbw = aw;
- *lbo = offset;
- *lbsp = s;
- if (*force_fit && *lbw >= widthLeft)
- return TRUE;
- *force_fit = FALSE;
- } else
- return TRUE;
- return FALSE;
- }
- static HTMLFitType
- hts_fit_line (HTMLObject *o,
- HTMLPainter *painter,
- gboolean lineBegin,
- gboolean firstRun,
- gboolean next_to_floating,
- gint widthLeft)
- {
- HTMLTextSlave *slave = HTML_TEXT_SLAVE (o);
- gint lbw, w, lbo, lwl, offset;
- gint ii, io, line_offset;
- gchar *s, *lbsp;
- HTMLFitType rv = HTML_FIT_NONE;
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gboolean force_fit = lineBegin;
- if (slave->posLen == 0)
- return HTML_FIT_COMPLETE;
- widthLeft = html_painter_engine_to_pango (painter, widthLeft);
- lbw = lwl = w = 0;
- offset = lbo = slave->posStart;
- ii = html_text_get_item_index (slave->owner, painter, offset, &io);
- line_offset = html_text_get_line_offset (slave->owner, painter, offset);
- lbsp = s = html_text_slave_get_text (slave);
- while ((force_fit || widthLeft > lbw) && offset < slave->posStart + slave->posLen) {
- if (offset > slave->posStart && offset > lbo && html_text_is_line_break (pi->attrs[offset]))
- if (update_lb (slave, painter, widthLeft, offset, s, ii, io, line_offset, w, &lwl, &lbw, &lbo, &lbsp, &force_fit))
- break;
- if (io == 0 && slave->owner->text[pi->entries[ii].glyph_item.item->offset] == '\t') {
- GtkHTMLFontStyle font_style;
- gchar *face;
- gint skip = 8 - (line_offset % 8);
- if (HTML_IS_PLAIN_PAINTER (painter)) {
- font_style = GTK_HTML_FONT_STYLE_FIXED;
- face = NULL;
- } else {
- font_style = html_text_get_font_style (slave->owner);
- face = slave->owner->face;
- }
- pi->entries[ii].glyph_item.glyphs->glyphs[0].geometry.width = pi->entries[ii].widths[io]
- = skip * html_painter_get_space_width (painter, font_style, face) * PANGO_SCALE;
- line_offset += skip;
- } else {
- line_offset++;
- }
- w += pi->entries[ii].widths[io];
- html_text_pi_forward (pi, &ii, &io);
- s = g_utf8_next_char (s);
- offset++;
- }
- if (offset == slave->posStart + slave->posLen && (widthLeft >= w || force_fit)) {
- rv = HTML_FIT_COMPLETE;
- if (slave->posLen)
- o->width = html_painter_pango_to_engine (painter, w);
- } else if (lbo > slave->posStart) {
- split (slave, lbo - slave->posStart - lwl, lwl, lbsp);
- rv = HTML_FIT_PARTIAL;
- o->width = html_painter_pango_to_engine (painter, lbw);
- o->change |= HTML_CHANGE_RECALC_PI;
- }
- return rv;
- }
- static gboolean
- select_range (HTMLObject *self,
- HTMLEngine *engine,
- guint start,
- gint length,
- gboolean queue_draw)
- {
- return FALSE;
- }
- static guint
- get_length (HTMLObject *self)
- {
- return 0;
- }
- /* HTMLObject::draw() implementation. */
- static gint
- get_ys (HTMLText *text,
- HTMLPainter *p)
- {
- if (text->font_style & GTK_HTML_FONT_STYLE_SUBSCRIPT || text->font_style & GTK_HTML_FONT_STYLE_SUPERSCRIPT) {
- gint height2;
- height2 = (HTML_OBJECT (text)->ascent + HTML_OBJECT (text)->descent) / 2;
- /* FIX2? (html_painter_calc_ascent (p, text->font_style, text->face)
- * + html_painter_calc_descent (p, text->font_style, text->face)) >> 1; */
- return (text->font_style & GTK_HTML_FONT_STYLE_SUBSCRIPT) ? height2 : -height2;
- } else
- return 0;
- }
- static inline GList *
- get_glyphs_base_text (GList *glyphs,
- PangoItem *item,
- gint ii,
- const gchar *text,
- gint bytes)
- {
- PangoGlyphString *str;
- str = pango_glyph_string_new ();
- pango_shape (text, bytes, &item->analysis, str);
- glyphs = g_list_prepend (glyphs, str);
- glyphs = g_list_prepend (glyphs, GINT_TO_POINTER (ii));
- return glyphs;
- }
- GList *
- html_get_glyphs_non_tab (GList *glyphs,
- PangoItem *item,
- gint ii,
- const gchar *text,
- gint bytes,
- gint len)
- {
- gchar *tab;
- while ((tab = memchr (text, (guchar) '\t', bytes))) {
- gint c_bytes = tab - text;
- if (c_bytes > 0)
- glyphs = get_glyphs_base_text (glyphs, item, ii, text, c_bytes);
- text += c_bytes + 1;
- bytes -= c_bytes + 1;
- }
- if (bytes > 0)
- glyphs = get_glyphs_base_text (glyphs, item, ii, text, bytes);
- return glyphs;
- }
- /*
- * NB: This implement the exact same algorithm as
- * reorder-items.c:pango_reorder_items().
- */
- static GSList *
- reorder_glyph_items (GSList *glyph_items,
- gint n_items)
- {
- GSList *tmp_list, *level_start_node;
- gint i, level_start_i;
- gint min_level = G_MAXINT;
- GSList *result = NULL;
- if (n_items == 0)
- return NULL;
- tmp_list = glyph_items;
- for (i = 0; i < n_items; i++) {
- HTMLTextSlaveGlyphItem *gi = tmp_list->data;
- min_level = MIN (min_level, gi->glyph_item.item->analysis.level);
- tmp_list = tmp_list->next;
- }
- level_start_i = 0;
- level_start_node = glyph_items;
- tmp_list = glyph_items;
- for (i = 0; i < n_items; i++) {
- HTMLTextSlaveGlyphItem *gi= tmp_list->data;
- if (gi->glyph_item.item->analysis.level == min_level) {
- if (min_level % 2) {
- if (i > level_start_i)
- result = g_slist_concat (reorder_glyph_items (level_start_node, i - level_start_i), result);
- result = g_slist_prepend (result, gi);
- } else {
- if (i > level_start_i)
- result = g_slist_concat (result, reorder_glyph_items (level_start_node, i - level_start_i));
- result = g_slist_append (result, gi);
- }
- level_start_i = i + 1;
- level_start_node = tmp_list->next;
- }
- tmp_list = tmp_list->next;
- }
- if (min_level % 2) {
- if (i > level_start_i)
- result = g_slist_concat (reorder_glyph_items (level_start_node, i - level_start_i), result);
- } else {
- if (i > level_start_i)
- result = g_slist_concat (result, reorder_glyph_items (level_start_node, i - level_start_i));
- }
- return result;
- }
- static GSList *
- get_glyph_items_in_range (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint start_offset,
- gint len)
- {
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gint i, offset, end_offset, n_items = 0;
- GSList *glyph_items = NULL;
- start_offset += slave->posStart;
- end_offset = start_offset + len;
- for (offset = 0, i = 0; i < pi->n; i++) {
- PangoItem *item = pi->entries[i].glyph_item.item;
- /* do item and slave overlap? */
- if (MAX (offset, start_offset) < MIN (offset + item->num_chars, end_offset)) {
- HTMLTextSlaveGlyphItem *glyph_item = g_new (HTMLTextSlaveGlyphItem, 1);
- /* use text glyph item */
- glyph_item->type = HTML_TEXT_SLAVE_GLYPH_ITEM_PARENTAL;
- glyph_item->glyph_item = pi->entries[i].glyph_item;
- glyph_item->widths = pi->entries[i].widths;
- if (start_offset > offset) {
- /* need to cut the beginning of current glyph item */
- PangoGlyphItem *tmp_gi;
- gint split_index;
- glyph_item->type = HTML_TEXT_SLAVE_GLYPH_ITEM_CREATED;
- glyph_item->widths = NULL;
- glyph_item->glyph_item.item = pango_item_copy (glyph_item->glyph_item.item);
- glyph_item->glyph_item.glyphs = pango_glyph_string_copy (glyph_item->glyph_item.glyphs);
- split_index = g_utf8_offset_to_pointer (slave->owner->text + item->offset, start_offset - offset)
- - (slave->owner->text + item->offset);
- tmp_gi = pango_glyph_item_split (&glyph_item->glyph_item, slave->owner->text, split_index);
- /* free the beginning we don't need */
- pango_glyph_item_free (tmp_gi);
- }
- if (offset + item->num_chars > end_offset) {
- /* need to cut the ending of current glyph item */
- PangoGlyphItem tmp_gi1, *tmp_gi2;
- gint split_index;
- if (glyph_item->type == HTML_TEXT_SLAVE_GLYPH_ITEM_PARENTAL) {
- tmp_gi1.item = pango_item_copy (glyph_item->glyph_item.item);
- tmp_gi1.glyphs = pango_glyph_string_copy (glyph_item->glyph_item.glyphs);
- } else
- tmp_gi1 = glyph_item->glyph_item;
- split_index = g_utf8_offset_to_pointer (slave->owner->text + tmp_gi1.item->offset, end_offset - MAX (start_offset, offset))
- - (slave->owner->text + tmp_gi1.item->offset);
- tmp_gi2 = pango_glyph_item_split (&tmp_gi1, slave->owner->text, split_index);
- glyph_item->glyph_item = *tmp_gi2;
- tmp_gi2->item = NULL;
- tmp_gi2->glyphs = NULL;
- /* free the tmp1 content and tmp2 container, but not the content */
- pango_item_free (tmp_gi1.item);
- pango_glyph_string_free (tmp_gi1.glyphs);
- pango_glyph_item_free (tmp_gi2);
- glyph_item->type = HTML_TEXT_SLAVE_GLYPH_ITEM_CREATED;
- glyph_item->widths = NULL;
- }
- glyph_items = g_slist_prepend (glyph_items, glyph_item);
- n_items++;
- }
- if (offset + item->num_chars >= end_offset)
- break;
- offset += item->num_chars;
- }
- if (glyph_items) {
- GSList *reversed;
- reversed = g_slist_reverse (glyph_items);
- glyph_items = reorder_glyph_items (reversed, n_items);
- g_slist_free (reversed);
- }
- return glyph_items;
- }
- GSList *
- html_text_slave_get_glyph_items (HTMLTextSlave *slave,
- HTMLPainter *painter)
- {
- if (painter && (!slave->glyph_items || (HTML_OBJECT (slave)->change & HTML_CHANGE_RECALC_PI))) {
- clear_glyph_items (slave);
- HTML_OBJECT (slave)->change &= ~HTML_CHANGE_RECALC_PI;
- slave->glyph_items = get_glyph_items_in_range (slave, painter, 0, slave->posLen);
- }
- return slave->glyph_items;
- }
- static gboolean
- calc_glyph_range_size (HTMLText *text,
- PangoGlyphItem *glyph_item,
- gint start_index,
- gint end_index,
- gint *x_offset,
- gint *width,
- gint *asc,
- gint *height)
- {
- gint isect_start, isect_end;
- isect_start = MAX (glyph_item->item->offset, start_index);
- isect_end = MIN (glyph_item->item->offset + glyph_item->item->length, end_index);
- isect_start -= glyph_item->item->offset;
- isect_end -= glyph_item->item->offset;
- /* printf ("calc_glyph_range_size isect start %d end %d (end_index %d)\n", isect_start, isect_end, end_index); */
- if (isect_start <= isect_end) {
- PangoRectangle log_rect;
- gint start_x, end_x;
- pango_glyph_string_index_to_x (glyph_item->glyphs,
- text->text + glyph_item->item->offset,
- glyph_item->item->length,
- &glyph_item->item->analysis,
- isect_start,
- FALSE, &start_x);
- if (isect_start < isect_end)
- pango_glyph_string_index_to_x (glyph_item->glyphs,
- text->text + glyph_item->item->offset,
- glyph_item->item->length,
- &glyph_item->item->analysis,
- isect_end,
- FALSE, &end_x);
- else
- end_x = start_x;
- if (asc || height)
- /* this call is used only to get ascent and height */
- pango_glyph_string_extents (glyph_item->glyphs, glyph_item->item->analysis.font, NULL, &log_rect);
- /* printf ("selection_start_index %d selection_end_index %d isect_start %d isect_end %d start_x %d end_x %d cwidth %d width %d\n",
- * selection_start_index, selection_end_index, isect_start, isect_end,
- * html_painter_pango_to_engine (p, start_x), html_painter_pango_to_engine (p, end_x),
- * html_painter_pango_to_engine (p, start_x < end_x ? (end_x - start_x) : (start_x - end_x)),
- * html_painter_pango_to_engine (p, log_rect.width)); */
- if (x_offset)
- *x_offset = MIN (start_x, end_x);
- if (width)
- *width = start_x < end_x ? (end_x - start_x) : (start_x - end_x);
- if (asc)
- *asc = PANGO_ASCENT (log_rect);
- if (height)
- *height = log_rect.height;
- return TRUE;
- }
- return FALSE;
- }
- static void
- draw_text (HTMLTextSlave *self,
- HTMLPainter *p,
- GtkHTMLFontStyle font_style,
- gint x,
- gint y,
- gint width,
- gint height,
- gint tx,
- gint ty)
- {
- HTMLObject *obj;
- HTMLText *text = self->owner;
- GSList *cur;
- gint run_width;
- gint selection_start_index = 0;
- gint selection_end_index = 0;
- gint isect_start, isect_end;
- gboolean selection;
- GdkColor selection_fg, selection_bg;
- HTMLEngine *e = NULL;
- obj = HTML_OBJECT (self);
- isect_start = MAX (text->select_start, self->posStart);
- isect_end = MIN (text->select_start + text->select_length, self->posStart + self->posLen);
- selection = isect_start < isect_end;
- if (p->widget && GTK_IS_HTML (p->widget))
- e = html_object_engine (HTML_OBJECT (self->owner), GTK_HTML (p->widget)->engine);
- if (selection) {
- gchar *end;
- gchar *start;
- start = html_text_get_text (text, isect_start);
- end = g_utf8_offset_to_pointer (start, isect_end - isect_start);
- selection_start_index = start - text->text;
- selection_end_index = end - text->text;
- if (e) {
- selection_fg = html_colorset_get_color_allocated
- (e->settings->color_set, p,
- p->focus ? HTMLHighlightTextColor : HTMLHighlightTextNFColor)->color;
- selection_bg = html_colorset_get_color_allocated
- (e->settings->color_set, p,
- p->focus ? HTMLHighlightColor : HTMLHighlightNFColor)->color;
- }
- }
- /* printf ("draw_text %d %d %d\n", selection_bg.red, selection_bg.green, selection_bg.blue); */
- run_width = 0;
- for (cur = html_text_slave_get_glyph_items (self, p); cur; cur = cur->next) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) cur->data;
- GList *cur_se;
- gint cur_width;
- if (e)
- html_painter_set_pen (p, &html_colorset_get_color_allocated (e->settings->color_set,
- e->painter, HTMLTextColor)->color);
- cur_width = html_painter_draw_glyphs (p, obj->x + tx + html_painter_pango_to_engine (p, run_width),
- obj->y + ty + get_ys (text, p), gi->glyph_item.item, gi->glyph_item.glyphs, NULL, NULL);
- if (selection) {
- gint start_x, width, asc, height;
- gint cx, cy, cw, ch;
- if (calc_glyph_range_size (text, &gi->glyph_item, selection_start_index, selection_end_index, &start_x, &width, &asc, &height) && width > 0) {
- html_painter_get_clip_rectangle (p, &cx, &cy, &cw, &ch);
- /* printf ("run_width; %d start_x %d index %d\n", run_width, start_x, selection_start_index); */
- html_painter_set_clip_rectangle (p,
- obj->x + tx + html_painter_pango_to_engine (p, run_width + start_x),
- obj->y + ty + get_ys (text, p) - html_painter_pango_to_engine (p, asc),
- html_painter_pango_to_engine (p, width),
- html_painter_pango_to_engine (p, height));
- /* printf ("draw selection %d %d %d at %d, %d\n", selection_bg.red, selection_bg.green, selection_bg.blue,
- * obj->x + tx + run_width, obj->y + ty + get_ys (text, p)); */
- html_painter_draw_glyphs (p, obj->x + tx + html_painter_pango_to_engine (p, run_width),
- obj->y + ty + get_ys (text, p), gi->glyph_item.item, gi->glyph_item.glyphs,
- &selection_fg, &selection_bg);
- html_painter_set_clip_rectangle (p, cx, cy, cw, ch);
- }
- }
- for (cur_se = text->spell_errors; e && cur_se; cur_se = cur_se->next) {
- SpellError *se;
- guint ma, mi;
- se = (SpellError *) cur_se->data;
- ma = MAX (se->off, self->posStart);
- mi = MIN (se->off + se->len, self->posStart + self->posLen);
- if (ma < mi) {
- gint width, height, asc, start_x;
- gchar *end;
- gchar *start;
- gint se_start_index, se_end_index;
- start = html_text_get_text (text, ma);
- end = g_utf8_offset_to_pointer (start, mi - ma);
- se_start_index = start - text->text;
- se_end_index = end - text->text;
- if (calc_glyph_range_size (text, &gi->glyph_item, se_start_index, se_end_index, &start_x, &width, &asc, &height)) {
- html_painter_set_pen (p, &html_colorset_get_color_allocated (e->settings->color_set,
- p, HTMLSpellErrorColor)->color);
- /* printf ("spell error: %s\n", html_text_get_text (slave->owner, off)); */
- html_painter_draw_spell_error (p, obj->x + tx + html_painter_pango_to_engine (p, run_width + start_x),
- obj->y + ty + get_ys (self->owner, p), html_painter_pango_to_engine (p, width));
- }
- }
- if (se->off > self->posStart + self->posLen)
- break;
- }
- run_width += cur_width;
- }
- }
- static void
- draw_focus_rectangle (HTMLTextSlave *slave,
- HTMLPainter *painter,
- GdkRectangle *box)
- {
- HTMLGdkPainter *p;
- const double dashes[] = { 1, 2 };
- gint ndash = G_N_ELEMENTS (dashes);
- HTMLEngine *e;
- if (painter->widget && GTK_IS_HTML (painter->widget))
- e = html_object_engine (HTML_OBJECT (slave->owner), GTK_HTML (painter->widget)->engine);
- else
- return;
- if (HTML_IS_PRINTER (painter))
- return;
- p = HTML_GDK_PAINTER (painter);
- /* printf ("draw_text_focus\n"); */
- cairo_save (p->cr);
- gdk_cairo_set_source_color (p->cr,
- &html_colorset_get_color_allocated (e->settings->color_set,
- painter, HTMLTextColor)->color);
- cairo_set_line_cap (p->cr, CAIRO_LINE_CAP_ROUND);
- cairo_set_line_width (p->cr, 1);
- cairo_set_dash (p->cr, dashes, ndash, 2);
- cairo_rectangle (
- p->cr,
- box->x - p->x1 - 0.5,
- box->y - p->y1 + 0.5,
- box->width + 1, box->height);
- cairo_stroke (p->cr);
- cairo_restore (p->cr);
- }
- static void
- draw_focus (HTMLTextSlave *slave,
- HTMLPainter *p,
- gint tx,
- gint ty)
- {
- GdkRectangle rect;
- Link *link = html_text_get_link_at_offset (slave->owner, slave->owner->focused_link_offset);
- if (link && MAX (link->start_offset, slave->posStart) < MIN (link->end_offset, slave->posStart + slave->posLen)) {
- gint bw = 0;
- html_object_get_bounds (HTML_OBJECT (slave), &rect);
- if (slave->posStart < link->start_offset)
- bw = html_text_calc_part_width (slave->owner, p, html_text_slave_get_text (slave),
- slave->posStart, link->start_offset - slave->posStart, NULL, NULL);
- rect.x += tx + bw;
- rect.width -= bw;
- if (slave->posStart + slave->posLen > link->end_offset)
- rect.width -= html_text_calc_part_width (slave->owner, p, slave->owner->text + link->end_index, link->end_offset,
- slave->posStart + slave->posLen - link->end_offset, NULL, NULL);
- rect.y += ty;
- draw_focus_rectangle (slave, p, &rect);
- }
- }
- static void
- draw (HTMLObject *o,
- HTMLPainter *p,
- gint x,
- gint y,
- gint width,
- gint height,
- gint tx,
- gint ty)
- {
- HTMLTextSlave *slave;
- HTMLText *owner;
- GtkHTMLFontStyle font_style;
- GdkRectangle paint;
- /* printf ("slave draw %p\n", o); */
- slave = HTML_TEXT_SLAVE (o);
- if (!html_object_intersect (o, &paint, x, y, width, height) || slave->posLen == 0)
- return;
- owner = slave->owner;
- font_style = html_text_get_font_style (owner);
- draw_text (slave, p, font_style, x, y, width, height, tx, ty);
- if (HTML_OBJECT (owner)->draw_focused)
- draw_focus (slave, p, tx, ty);
- }
- static gint
- calc_min_width (HTMLObject *o,
- HTMLPainter *painter)
- {
- return 0;
- }
- static gint
- calc_preferred_width (HTMLObject *o,
- HTMLPainter *painter)
- {
- return 0;
- }
- static const gchar *
- get_url (HTMLObject *o,
- gint offset)
- {
- HTMLTextSlave *slave;
- slave = HTML_TEXT_SLAVE (o);
- return html_object_get_url (HTML_OBJECT (slave->owner), offset);
- }
- static gint
- calc_offset (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint x)
- {
- GSList *cur, *glyphs = html_text_slave_get_glyph_items (slave, painter);
- gint width = 0, offset = html_object_get_direction (HTML_OBJECT (slave->owner)) == HTML_DIRECTION_RTL ? slave->posLen : 0;
- PangoItem *item = NULL;
- if (glyphs) {
- gint i = 0;
- for (cur = glyphs; cur; cur = cur->next) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) cur->data;
- item = gi->glyph_item.item;
- if (gi->widths == NULL) {
- gi->widths = g_new (PangoGlyphUnit, item->num_chars);
- html_tmp_fix_pango_glyph_string_get_logical_widths (gi->glyph_item.glyphs, slave->owner->text + item->offset, item->length,
- item->analysis.level, gi->widths);
- }
- if (item->analysis.level % 2 == 0) {
- /* LTR */
- for (i = 0; i < item->num_chars; i++) {
- if (x < html_painter_pango_to_engine (painter, width + gi->widths[i] / 2))
- goto done;
- width += gi->widths[i];
- }
- } else {
- /* RTL */
- for (i = item->num_chars - 1; i >= 0; i--) {
- if (x < html_painter_pango_to_engine (painter, width + gi->widths[i] / 2)) {
- i++;
- goto done;
- }
- width += gi->widths[i];
- }
- }
- }
- done:
- if (cur)
- offset = g_utf8_pointer_to_offset (html_text_slave_get_text (slave), slave->owner->text + item->offset) + i;
- else {
- offset = html_object_get_direction (HTML_OBJECT (slave->owner)) == HTML_DIRECTION_RTL ? 0 : slave->posLen;
- }
- }
- /* printf ("offset %d\n", offset); */
- return offset;
- }
- static guint
- get_offset_for_pointer (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint x,
- gint y)
- {
- g_return_val_if_fail (slave != NULL, 0);
- x -= HTML_OBJECT (slave)->x;
- if (x <= 0)
- return 0;
- if (x >= HTML_OBJECT (slave)->width - 1)
- return slave->posLen;
- if (slave->posLen > 1)
- return calc_offset (slave, painter, x);
- else
- return x > HTML_OBJECT (slave)->width / 2 ? 1 : 0;
- }
- static HTMLObject *
- check_point (HTMLObject *self,
- HTMLPainter *painter,
- gint x,
- gint y,
- guint *offset_return,
- gboolean for_cursor)
- {
- if (x >= self->x
- && x < self->x + MAX (1, self->width)
- && y >= self->y - self->ascent
- && y < self->y + self->descent) {
- HTMLTextSlave *slave = HTML_TEXT_SLAVE (self);
- if (offset_return != NULL)
- *offset_return = slave->posStart
- + get_offset_for_pointer (slave, painter, x, y);
- return HTML_OBJECT (slave->owner);
- }
- return NULL;
- }
- static void
- clear_glyph_items (HTMLTextSlave *slave)
- {
- if (slave->glyph_items) {
- glyph_items_destroy (slave->glyph_items);
- slave->glyph_items = NULL;
- }
- }
- static void
- destroy (HTMLObject *obj)
- {
- HTMLTextSlave *slave = HTML_TEXT_SLAVE (obj);
- clear_glyph_items (slave);
- HTML_OBJECT_CLASS (parent_class)->destroy (obj);
- }
- void
- html_text_slave_type_init (void)
- {
- html_text_slave_class_init (&html_text_slave_class, HTML_TYPE_TEXTSLAVE, sizeof (HTMLTextSlave));
- }
- void
- html_text_slave_class_init (HTMLTextSlaveClass *klass,
- HTMLType type,
- guint object_size)
- {
- HTMLObjectClass *object_class;
- object_class = HTML_OBJECT_CLASS (klass);
- html_object_class_init (object_class, type, object_size);
- object_class->select_range = select_range;
- object_class->copy = copy;
- object_class->destroy = destroy;
- object_class->draw = draw;
- object_class->calc_size = html_text_slave_real_calc_size;
- object_class->fit_line = hts_fit_line;
- object_class->calc_min_width = calc_min_width;
- object_class->calc_preferred_width = calc_preferred_width;
- object_class->get_url = get_url;
- object_class->get_length = get_length;
- object_class->check_point = check_point;
- parent_class = &html_object_class;
- }
- void
- html_text_slave_init (HTMLTextSlave *slave,
- HTMLTextSlaveClass *klass,
- HTMLText *owner,
- guint posStart,
- guint posLen)
- {
- HTMLObject *object;
- object = HTML_OBJECT (slave);
- html_object_init (object, HTML_OBJECT_CLASS (klass));
- object->ascent = HTML_OBJECT (owner)->ascent;
- object->descent = HTML_OBJECT (owner)->descent;
- slave->posStart = posStart;
- slave->posLen = posLen;
- slave->owner = owner;
- slave->charStart = NULL;
- slave->pi = NULL;
- slave->glyph_items = NULL;
- /* text slaves have always min_width 0 */
- object->min_width = 0;
- object->change &= ~HTML_CHANGE_MIN_WIDTH;
- }
- HTMLObject *
- html_text_slave_new (HTMLText *owner,
- guint posStart,
- guint posLen)
- {
- HTMLTextSlave *slave;
- slave = g_new (HTMLTextSlave, 1);
- html_text_slave_init (slave, &html_text_slave_class, owner, posStart, posLen);
- return HTML_OBJECT (slave);
- }
- static gboolean
- html_text_slave_is_index_in_glyph (HTMLTextSlave *slave,
- HTMLTextSlave *next_slave,
- GSList *cur,
- gint index,
- PangoItem *item)
- {
- if (item->analysis.level % 2 == 0) {
- /* LTR */
- return item->offset <= index
- && (index < item->offset + item->length
- || (index == item->offset + item->length &&
- (!cur->next
- || (!next_slave && slave->owner->text_bytes == item->offset + item->length)
- || (next_slave && html_text_slave_get_text (next_slave) - next_slave->owner->text == item->offset + item->length))));
- } else {
- /* RTL */
- return index <= item->offset + item->length
- && (item->offset < index
- || (index == item->offset &&
- (!cur->next
- || (!next_slave && slave->owner->text_bytes == item->offset + item->length)
- || (next_slave && html_text_slave_get_text (next_slave) - next_slave->owner->text == item->offset))));
- }
- }
- static HTMLTextSlaveGlyphItem *
- html_text_slave_get_glyph_item_at_offset (HTMLTextSlave *slave,
- HTMLPainter *painter,
- gint offset,
- HTMLTextSlaveGlyphItem **prev,
- HTMLTextSlaveGlyphItem **next,
- gint *start_width,
- gint *index_out)
- {
- HTMLTextSlaveGlyphItem *rv = NULL;
- HTMLTextSlaveGlyphItem *prev_gi, *next_gi;
- HTMLTextSlave *next_slave = HTML_OBJECT (slave)->next && HTML_IS_TEXT_SLAVE (HTML_OBJECT (slave)->next) ? HTML_TEXT_SLAVE (HTML_OBJECT (slave)->next) : NULL;
- GSList *cur;
- gint index;
- next_gi = NULL;
- index = g_utf8_offset_to_pointer (html_text_slave_get_text (slave), offset) - slave->owner->text;
- if (index_out)
- *index_out = index;
- if (start_width)
- *start_width = 0;
- cur = html_text_slave_get_glyph_items (slave, painter);
- if (cur) {
- for (prev_gi = NULL; cur; cur = cur->next) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) cur->data;
- if (html_text_slave_is_index_in_glyph (slave, next_slave, cur, index, gi->glyph_item.item)) {
- next_gi = cur->next ? (HTMLTextSlaveGlyphItem *) cur->next->data : NULL;
- rv = gi;
- break;
- }
- prev_gi = gi;
- if (start_width) {
- PangoRectangle log_rect;
- pango_glyph_string_extents (gi->glyph_item.glyphs, gi->glyph_item.item->analysis.font, NULL, &log_rect);
- (*start_width) += log_rect.width;
- }
- }
- } else {
- prev_gi = next_gi = NULL;
- }
- if (prev)
- *prev = prev_gi;
- if (next)
- *next = next_gi;
- return rv;
- }
- static gboolean
- html_text_slave_gi_left_edge (HTMLTextSlave *slave,
- HTMLCursor *cursor,
- HTMLTextSlaveGlyphItem *gi)
- {
- gint old_offset = cursor->offset;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- cursor->offset = slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text + gi->glyph_item.item->offset);
- cursor->position += cursor->offset - old_offset;
- } else {
- /* RTL */
- cursor->offset = slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text + gi->glyph_item.item->offset + gi->glyph_item.item->length);
- cursor->position += cursor->offset - old_offset;
- }
- return TRUE;
- }
- static gboolean
- html_text_slave_gi_right_edge (HTMLTextSlave *slave,
- HTMLCursor *cursor,
- HTMLTextSlaveGlyphItem *gi)
- {
- gint old_offset = cursor->offset;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- cursor->offset = slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text + gi->glyph_item.item->offset + gi->glyph_item.item->length);
- cursor->position += cursor->offset - old_offset;
- } else {
- /* RTL */
- cursor->offset = slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text + gi->glyph_item.item->offset);
- cursor->position += cursor->offset - old_offset;
- }
- return TRUE;
- }
- static gboolean
- html_text_slave_cursor_right_one (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextSlaveGlyphItem *prev, *next;
- gint index;
- HTMLTextSlaveGlyphItem *gi = html_text_slave_get_glyph_item_at_offset (slave, painter, cursor->offset - slave->posStart, &prev, &next, NULL, &index);
- if (!gi)
- return FALSE;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- if (index < gi->glyph_item.item->offset + gi->glyph_item.item->length) {
- cursor->offset++;
- cursor->position++;
- return TRUE;
- }
- } else {
- /* RTL */
- if (index > gi->glyph_item.item->offset && index <= gi->glyph_item.item->offset + gi->glyph_item.item->length) {
- cursor->offset--;
- cursor->position--;
- return TRUE;
- }
- }
- if (next) {
- if (html_text_slave_gi_left_edge (slave, cursor, next)) {
- if (next->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- cursor->offset++;
- cursor->position++;
- } else {
- /* RTL */
- cursor->offset--;
- cursor->position--;
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- gboolean
- html_text_slave_cursor_right (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gboolean step_success;
- do
- step_success = html_text_slave_cursor_right_one (slave, painter, cursor);
- while (step_success && !pi->attrs[cursor->offset].is_cursor_position);
- return step_success;
- }
- static gboolean
- html_text_slave_cursor_left_one (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextSlaveGlyphItem *prev, *next;
- gint index;
- HTMLObject *prev_obj = HTML_OBJECT (slave->owner)->prev;
- HTMLTextSlaveGlyphItem *gi = html_text_slave_get_glyph_item_at_offset (slave, painter, cursor->offset - slave->posStart, &prev, &next, NULL, &index);
- /* printf ("gi: %p item num chars: %d\n", gi, gi ? gi->glyph_item.item->num_chars : -1); */
- if (!gi)
- return FALSE;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- if (index - gi->glyph_item.item->offset > 1 || (!prev && !prev_obj && index - gi->glyph_item.item->offset > 0)) {
- cursor->offset--;
- cursor->position--;
- return TRUE;
- }
- } else {
- /* RTL */
- if (index < gi->glyph_item.item->offset + gi->glyph_item.item->length) {
- cursor->offset++;
- cursor->position++;
- return TRUE;
- }
- }
- if (prev) {
- if (html_text_slave_gi_right_edge (slave, cursor, prev)) {
- if (prev->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- if (index - gi->glyph_item.item->offset == 0) {
- cursor->offset--;
- cursor->position--;
- }
- } else {
- /* RTL */
- cursor->offset++;
- cursor->position++;
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- gboolean
- html_text_slave_cursor_left (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gboolean step_success;
- do
- step_success = html_text_slave_cursor_left_one (slave, painter, cursor);
- while (step_success && !pi->attrs[cursor->offset].is_cursor_position);
- return step_success;
- }
- static gboolean
- html_text_slave_get_left_edge (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gint old_offset = cursor->offset;
- gint old_position = cursor->position;
- cursor->offset = html_text_slave_get_left_edge_offset (slave, painter);
- if (pi->attrs[cursor->offset].is_cursor_position && old_offset != cursor->offset)
- return TRUE;
- else {
- if (html_text_slave_cursor_right (slave, painter, cursor)) {
- /* we should preserve position here as caller function correct position themselves */
- cursor->position = old_position;
- return TRUE;
- } else
- return FALSE;
- }
- }
- static gboolean
- html_text_slave_get_right_edge (HTMLTextSlave *slave,
- HTMLPainter *painter,
- HTMLCursor *cursor)
- {
- HTMLTextPangoInfo *pi = html_text_get_pango_info (slave->owner, painter);
- gint old_offset = cursor->offset;
- gint old_position = cursor->position;
- cursor->offset = html_text_slave_get_right_edge_offset (slave, painter);
- if (pi->attrs[cursor->offset].is_cursor_position && old_offset != cursor->offset)
- return TRUE;
- else {
- if (html_text_slave_cursor_left (slave, painter, cursor)) {
- /* we should preserve position here as caller function correct position themselves */
- cursor->position = old_position;
- return TRUE;
- } else
- return FALSE;
- }
- }
- gboolean
- html_text_slave_cursor_head (HTMLTextSlave *slave,
- HTMLCursor *cursor,
- HTMLPainter *painter)
- {
- if (html_text_slave_get_glyph_items (slave, painter)) {
- cursor->object = HTML_OBJECT (slave->owner);
- if (html_text_get_pango_direction (slave->owner) != PANGO_DIRECTION_RTL) {
- /* LTR */
- return html_text_slave_get_left_edge (slave, painter, cursor);
- } else {
- /* RTL */
- return html_text_slave_get_right_edge (slave, painter, cursor);
- }
- }
- return FALSE;
- }
- gboolean
- html_text_slave_cursor_tail (HTMLTextSlave *slave,
- HTMLCursor *cursor,
- HTMLPainter *painter)
- {
- if (html_text_slave_get_glyph_items (slave, painter)) {
- cursor->object = HTML_OBJECT (slave->owner);
- if (html_text_get_pango_direction (slave->owner) != PANGO_DIRECTION_RTL) {
- /* LTR */
- return html_text_slave_get_right_edge (slave, painter, cursor);
- } else {
- /* RTL */
- return html_text_slave_get_left_edge (slave, painter, cursor);
- }
- }
- return FALSE;
- }
- void
- html_text_slave_get_cursor_base (HTMLTextSlave *slave,
- HTMLPainter *painter,
- guint offset,
- gint *x,
- gint *y)
- {
- HTMLTextSlaveGlyphItem *gi;
- gint index, start_width;
- html_object_calc_abs_position (HTML_OBJECT (slave), x, y);
- gi = html_text_slave_get_glyph_item_at_offset (slave, painter, (gint) offset, NULL, NULL, &start_width, &index);
- /* printf ("gi: %p index: %d start_width: %d item indexes %d %d\n", */
- /* gi, index, start_width, gi ? gi->glyph_item.item->offset : -1, */
- /* gi ? gi->glyph_item.item->offset + gi->glyph_item.item->length : -1); */
- if (gi) {
- gint start_x;
- if (calc_glyph_range_size (slave->owner, &gi->glyph_item, index, index, &start_x, NULL, NULL, NULL) && x) {
- /* printf ("start_width: %d start_x: %d\n", start_width, start_x); */
- *x += html_painter_pango_to_engine (painter, start_width + start_x);
- }
- }
- }
- gint
- html_text_slave_get_left_edge_offset (HTMLTextSlave *slave,
- HTMLPainter *painter)
- {
- GSList *gis = html_text_slave_get_glyph_items (slave, painter);
- if (gis) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) gis->data;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- return slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave), slave->owner->text + gi->glyph_item.item->offset);
- } else {
- /* RTL */
- return slave->posStart + MIN (slave->posLen, g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text
- + gi->glyph_item.item->offset + gi->glyph_item.item->length));
- }
- } else {
- if (slave->owner->text_len > 0)
- g_warning ("html_text_slave_get_left_edge_offset failed");
- return 0;
- }
- }
- gint
- html_text_slave_get_right_edge_offset (HTMLTextSlave *slave,
- HTMLPainter *painter)
- {
- GSList *gis = html_text_slave_get_glyph_items (slave, painter);
- if (gis) {
- HTMLTextSlaveGlyphItem *gi = (HTMLTextSlaveGlyphItem *) g_slist_last (gis)->data;
- if (gi->glyph_item.item->analysis.level % 2 == 0) {
- /* LTR */
- return slave->posStart + MIN (slave->posLen, g_utf8_pointer_to_offset (html_text_slave_get_text (slave),
- slave->owner->text
- + gi->glyph_item.item->offset + gi->glyph_item.item->length));
- } else {
- /* RTL */
- return slave->posStart + g_utf8_pointer_to_offset (html_text_slave_get_text (slave), slave->owner->text + gi->glyph_item.item->offset);
- }
- } else {
- if (slave->owner->text_len > 0)
- g_warning ("html_text_slave_get_left_edge_offset failed");
- return 0;
- }
- }