source: trunk/third/gtkhtml/src/htmlengine-search.c @ 17184

Revision 17184, 5.7 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17183, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*  This file is part of the GtkHTML library.
3
4    Copyright (C) 1999, 2000 Helix Code, Inc.
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.
20*/
21
22#include <config.h>
23#include <gal/unicode/gunicode.h>
24#include "htmlcursor.h"
25#include "htmlengine.h"
26#include "htmlengine-edit.h"
27#include "htmlengine-edit-cursor.h"
28#include "htmlengine-search.h"
29#include "htmlinterval.h"
30#include "htmlsearch.h"
31#include "htmlselection.h"
32#include "htmltextslave.h"
33
34static HTMLEngine *
35get_root_engine (HTMLEngine *e)
36{
37        return e->widget->iframe_parent ? GTK_HTML (e->widget->iframe_parent)->engine : e;
38}
39
40static void
41add_iframe_off (HTMLEngine *e, gint *x, gint *y)
42{
43        g_assert (e);
44        g_assert (e->widget);
45
46        if (e->widget->iframe_parent) {
47                *x += e->widget->iframe_parent->allocation.x;
48                *y += e->widget->iframe_parent->allocation.y;
49        }
50}
51
52static void
53move_to_found (HTMLSearch *info)
54{
55        HTMLEngine *e = info->engine;
56        HTMLEngine *ep = get_root_engine (info->engine);
57        HTMLObject *first = HTML_OBJECT (info->found->data);
58        HTMLObject *last = HTML_OBJECT (g_list_last (info->found)->data);
59        HTMLTextSlave *slave;
60        gint x, y, ex, ey, w, h;
61        gint nx = e->x_offset;
62        gint ny = e->y_offset;
63
64        /* x,y is top-left corner, ex+w,ey+h is bottom-right */
65        html_object_calc_abs_position (first, &x, &y);
66        add_iframe_off (e, &x, &y);
67
68        /* find slave where starts selection and get its coordinates as upper-left corner */
69        while (first->next && HTML_OBJECT_TYPE (first->next) == HTML_TYPE_TEXTSLAVE) {
70                first = first->next;
71                slave = HTML_TEXT_SLAVE (first);
72                if (slave->posStart+slave->posLen >= info->start_pos) {
73                        html_object_calc_abs_position (HTML_OBJECT (slave), &x, &y);
74                        add_iframe_off (e, &x, &y);
75                        break;
76                }
77        }
78
79        /* the same with last */
80        html_object_calc_abs_position (last, &ex, &ey);
81
82        while (last->next && HTML_OBJECT_TYPE (last->next) == HTML_TYPE_TEXTSLAVE) {
83                last = last->next;
84                slave = HTML_TEXT_SLAVE (last);
85                if (slave->posStart+slave->posLen >= info->start_pos) {
86                        html_object_calc_abs_position (HTML_OBJECT (slave), &ex, &ey);
87                        add_iframe_off (e, &ex, &ey);
88                        break;
89                }
90        }
91
92        y  -= first->ascent;
93        ex += last->width;
94        ey += last->descent;
95        w = ex - x;
96        h = ey - y;
97
98        /* now calculate gtkhtml adustments */
99        if (x <= ep->x_offset)
100                nx = x;
101        else if (x + w > ep->x_offset + ep->width)
102                nx = x + w - ep->width;
103
104        if (y <= ep->y_offset)
105                ny = y;
106        else if (y + h > ep->y_offset + ep->height)
107                ny = y + h - ep->height;
108
109        /* finally adjust them if they changed */
110        if (ep->x_offset != nx)
111                gtk_adjustment_set_value (GTK_LAYOUT (ep->widget)->hadjustment, nx);
112
113        if (ep->y_offset != ny)
114                gtk_adjustment_set_value (GTK_LAYOUT (ep->widget)->vadjustment, ny);
115}
116
117static void
118display_search_results (HTMLSearch *info)
119{
120        HTMLEngine *e = info->engine;
121
122        if (!info->found)
123                return;
124        if (e->editable) {
125                html_engine_hide_cursor (e);
126                html_engine_disable_selection (e);
127                html_cursor_jump_to (e->cursor, e, HTML_OBJECT (info->found->data), info->start_pos);
128                html_engine_set_mark (e);
129                html_cursor_jump_to (e->cursor, e, info->last, info->stop_pos);
130                html_engine_show_cursor (e);
131        } else {
132                html_engine_select_interval (e, html_interval_new (HTML_OBJECT (info->found->data), info->last,
133                                                                   info->start_pos, info->stop_pos));
134                move_to_found (info);
135        }
136}
137
138gboolean
139html_engine_search (HTMLEngine *e, const gchar *text,
140                    gboolean case_sensitive, gboolean forward, gboolean regular)
141{
142        HTMLSearch *info;
143        HTMLObject *p;
144
145        if (e->search_info) {
146                html_search_destroy (e->search_info);
147        }
148
149        info = e->search_info = html_search_new (e, text, case_sensitive, forward, regular);
150
151        p = HTML_OBJECT (e->search_info->stack->data)->parent;
152        if (html_object_search (p ? p : e->clue, info)) {
153                display_search_results (info);
154                return TRUE;
155        } else
156                return FALSE;
157}
158
159void
160html_engine_search_set_forward (HTMLEngine *e, gboolean forward)
161{
162        html_search_set_forward (e->search_info, forward);
163}
164
165gboolean
166html_engine_search_next (HTMLEngine *e)
167{
168        HTMLSearch *info = e->search_info;
169        gboolean retval = FALSE;
170
171        if (!info)
172                return FALSE;
173
174        if (html_engine_get_editable (e)) {
175                gchar *text = g_strdup (info->text);
176
177                retval = html_engine_search (e, text, info->case_sensitive, info->forward, info->regular);
178                g_free (text);
179        } else {
180                if (info->stack)
181                        retval = html_object_search (HTML_OBJECT (info->stack->data), info);
182                else {
183                        html_search_push (info, e->clue);
184                        retval = html_object_search (e->clue, info);
185                }
186                if (retval)
187                        display_search_results (info);
188                else {
189                        html_search_pop (info);
190                        html_engine_disable_selection (e);
191                }
192        }
193
194        return retval;
195}
196
197gboolean
198html_engine_search_incremental (HTMLEngine *e, const gchar *text, gboolean forward)
199{
200        HTMLSearch *info = e->search_info;     
201
202        if (info) {
203                html_search_set_forward (info, forward);
204                html_search_set_text (info, text);
205                if (info->found)
206                        info->start_pos += ((info->forward) ? -1 : g_utf8_strlen (text, -1));
207                return html_engine_search_next (e);
208        } else
209                return html_engine_search (e, text, FALSE, forward, FALSE);
210}
Note: See TracBrowser for help on using the repository browser.