1 
2 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* This file is part of the GtkHTML library.
4  *
5  * Copyright (C) 2000 Helix Code, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21 */
22 
23 #include <config.h>
24 #include <gtk/gtk.h>
25 #include <string.h>
26 #include "gtkhtml.h"
27 #include "gtkhtml-stream.h"
28 #include "htmltokenizer.h"
29 #include "gtkhtml-private.h"
30 #include "htmlcolorset.h"
31 #include "htmlgdkpainter.h"
32 #include "htmlprinter.h"
33 #include "htmlframe.h"
34 #include "htmlengine-search.h"
35 #include "htmlsearch.h"
36 #include "htmlselection.h"
37 #include "htmlsettings.h"
38 
39 HTMLFrameClass html_frame_class;
40 static HTMLEmbeddedClass *parent_class = NULL;
41 
42 static void
frame_url_requested(GtkHTML * html,const gchar * url,GtkHTMLStream * handle,gpointer data)43 frame_url_requested (GtkHTML *html,
44                      const gchar *url,
45                      GtkHTMLStream *handle,
46                      gpointer data)
47 {
48 	HTMLFrame *frame = HTML_FRAME (data);
49 	GtkHTML *parent = GTK_HTML (HTML_EMBEDDED (frame)->parent);
50 
51 	if (!html->engine->stopped)
52 		g_signal_emit_by_name (parent->engine, "url_requested", url, handle);
53 }
54 
55 static void
frame_set_base(GtkHTML * html,const gchar * url,gpointer data)56 frame_set_base (GtkHTML *html,
57                 const gchar *url,
58                 gpointer data)
59 {
60 	gchar *new_url = NULL;
61 
62 	new_url = gtk_html_get_url_base_relative (html, url);
63 	gtk_html_set_base (html, new_url);
64 	g_free (new_url);
65 }
66 
67 static void
frame_submit(GtkHTML * html,const gchar * method,const gchar * action,const gchar * encoding,gpointer data)68 frame_submit (GtkHTML *html,
69               const gchar *method,
70               const gchar *action,
71               const gchar *encoding,
72               gpointer data)
73 {
74 	HTMLFrame *frame = HTML_FRAME (data);
75 	GtkHTML *parent = GTK_HTML (HTML_EMBEDDED (frame)->parent);
76 
77 	g_signal_emit_by_name (parent, "submit", method, action, encoding);
78 }
79 
80 static void
frame_size_changed(GtkHTML * html,gpointer data)81 frame_size_changed (GtkHTML *html,
82                     gpointer data)
83 {
84 	HTMLFrame *frame = HTML_FRAME (data);
85 	GtkHTML *parent = GTK_HTML (HTML_EMBEDDED (frame)->parent);
86 
87 	html_engine_schedule_update (parent->engine);
88 }
89 
90 static gboolean
frame_object_requested(GtkHTML * html,GtkHTMLEmbedded * eb,gpointer data)91 frame_object_requested (GtkHTML *html,
92                         GtkHTMLEmbedded *eb,
93                         gpointer data)
94 {
95 	HTMLFrame *frame = HTML_FRAME (data);
96 	GtkHTML *parent = GTK_HTML (HTML_EMBEDDED (frame)->parent);
97 	gboolean ret_val;
98 
99 	ret_val = FALSE;
100 	g_signal_emit_by_name (parent, "object_requested", eb, &ret_val);
101 	return ret_val;
102 }
103 
104 static void
frame_set_gdk_painter(HTMLFrame * frame,HTMLPainter * painter)105 frame_set_gdk_painter (HTMLFrame *frame,
106                        HTMLPainter *painter)
107 {
108 	if (painter)
109 		g_object_ref (G_OBJECT (painter));
110 
111 	if (frame->gdk_painter)
112 		g_object_unref (G_OBJECT (frame->gdk_painter));
113 
114 	frame->gdk_painter = painter;
115 }
116 
117 HTMLObject *
html_frame_new(GtkWidget * parent,gchar * src,gint width,gint height,gboolean border)118 html_frame_new (GtkWidget *parent,
119                  gchar *src,
120                  gint width,
121                  gint height,
122                  gboolean border)
123 {
124 	HTMLFrame *frame;
125 
126 	frame = g_new (HTMLFrame, 1);
127 
128 	html_frame_init (frame,
129 			  &html_frame_class,
130 			  parent,
131 			  src,
132 			  width,
133 			  height,
134 			  border);
135 
136 	return HTML_OBJECT (frame);
137 }
138 
139 static gboolean
html_frame_grab_cursor(GtkWidget * frame,GdkEvent * event)140 html_frame_grab_cursor (GtkWidget *frame,
141                         GdkEvent *event)
142 {
143 	/* Keep the focus! Fight the power */
144 	return TRUE;
145 }
146 
147 static gint
calc_min_width(HTMLObject * o,HTMLPainter * painter)148 calc_min_width (HTMLObject *o,
149                 HTMLPainter *painter)
150 {
151   gint min_width;
152 
153   if (HTML_FRAME (o)->width < 0)
154 	  min_width =  html_engine_calc_min_width (GTK_HTML (HTML_FRAME (o)->html)->engine);
155   else
156 	  min_width = HTML_FRAME (o)->width;
157 
158   return min_width;
159 }
160 
161 static void
set_max_width(HTMLObject * o,HTMLPainter * painter,gint max_width)162 set_max_width (HTMLObject *o,
163                HTMLPainter *painter,
164                gint max_width)
165 {
166 	HTMLEngine *e = GTK_HTML (HTML_FRAME (o)->html)->engine;
167 
168 	o->max_width = max_width;
169 	html_object_set_max_width (e->clue, e->painter, max_width - (html_engine_get_left_border (e) + html_engine_get_right_border (e)));
170 }
171 
172 static void
draw(HTMLObject * o,HTMLPainter * p,gint x,gint y,gint width,gint height,gint tx,gint ty)173 draw (HTMLObject *o,
174       HTMLPainter *p,
175       gint x,
176       gint y,
177       gint width,
178       gint height,
179       gint tx,
180       gint ty)
181 {
182 	HTMLFrame   *frame  = HTML_FRAME (o);
183 	HTMLEngine   *e       = GTK_HTML (frame->html)->engine;
184 	GdkRectangle paint;
185 
186 	if (G_OBJECT_TYPE (e->painter) == HTML_TYPE_PRINTER) {
187 		gint pixel_size = html_painter_get_pixel_size (e->painter);
188 
189 		if (!html_object_intersect (o, &paint, x, y, width, height))
190 			return;
191 
192 		html_object_draw (e->clue, e->painter,
193 				  x, y,
194 				  width - pixel_size * (html_engine_get_left_border (e) + html_engine_get_right_border (e)),
195 				  height - pixel_size * (html_engine_get_top_border (e) + html_engine_get_bottom_border (e)),
196 				  tx + pixel_size * html_engine_get_left_border (e), ty + pixel_size * html_engine_get_top_border (e));
197 	} else
198 		(*HTML_OBJECT_CLASS (parent_class)->draw) (o, p, x, y, width, height, tx, ty);
199 }
200 
201 static void
set_painter(HTMLObject * o,HTMLPainter * painter)202 set_painter (HTMLObject *o,
203              HTMLPainter *painter)
204 {
205 	HTMLFrame *frame;
206 
207 	frame = HTML_FRAME (o);
208 	if (G_OBJECT_TYPE (GTK_HTML (frame->html)->engine->painter) != HTML_TYPE_PRINTER) {
209 		frame_set_gdk_painter (frame, GTK_HTML (frame->html)->engine->painter);
210 	}
211 
212 	html_engine_set_painter (GTK_HTML (frame->html)->engine,
213 				 G_OBJECT_TYPE (painter) != HTML_TYPE_PRINTER ? frame->gdk_painter : painter);
214 }
215 
216 static void
forall(HTMLObject * self,HTMLEngine * e,HTMLObjectForallFunc func,gpointer data)217 forall (HTMLObject *self,
218         HTMLEngine *e,
219         HTMLObjectForallFunc func,
220         gpointer data)
221 {
222 	HTMLFrame *frame;
223 
224 	frame = HTML_FRAME (self);
225 	(* func) (self, html_object_get_engine (self, e), data);
226 	html_object_forall (GTK_HTML (frame->html)->engine->clue, html_object_get_engine (self, e), func, data);
227 }
228 
229 static gint
check_page_split(HTMLObject * self,HTMLPainter * p,gint y)230 check_page_split (HTMLObject *self,
231                   HTMLPainter *p,
232                   gint y)
233 {
234 	return html_object_check_page_split (GTK_HTML (HTML_FRAME (self)->html)->engine->clue, p, y);
235 }
236 
237 static gboolean
html_frame_real_calc_size(HTMLObject * o,HTMLPainter * painter,GList ** changed_objs)238 html_frame_real_calc_size (HTMLObject *o,
239                            HTMLPainter *painter,
240                            GList **changed_objs)
241 {
242 	HTMLFrame *frame;
243 	HTMLEngine *e;
244 	gint old_width, old_ascent, old_descent;
245 
246 	old_width = o->width;
247 	old_ascent = o->ascent;
248 	old_descent = o->descent;
249 
250 	frame = HTML_FRAME (o);
251 	e     = GTK_HTML (frame->html)->engine;
252 
253 	if ((frame->width < 0) && (frame->height < 0)) {
254 		if (e->clue) {
255 			html_engine_calc_size (e, changed_objs);
256 			e->width = html_engine_get_doc_width (e);
257 			e->height = html_engine_get_doc_height (e);
258 		}
259 		html_frame_set_scrolling (frame, GTK_POLICY_NEVER);
260 
261 		o->width = e->width;
262 		o->ascent = e->height;
263 		o->descent = 0;
264 	} else
265 		return (* HTML_OBJECT_CLASS (parent_class)->calc_size) (o, painter, changed_objs);
266 
267 	if (o->descent != old_descent
268 	    || o->ascent != old_ascent
269 	    || o->width != old_width)
270 		return TRUE;
271 
272 	return FALSE;
273 }
274 
275 static gboolean
search(HTMLObject * self,HTMLSearch * info)276 search (HTMLObject *self,
277         HTMLSearch *info)
278 {
279 	HTMLEngine *e = GTK_HTML (HTML_FRAME (self)->html)->engine;
280 
281 	/* printf ("search\n"); */
282 
283 	/* search_next? */
284 	if (info->stack && HTML_OBJECT (info->stack->data) == e->clue) {
285 		/* printf ("next\n"); */
286 		info->engine = GTK_HTML (GTK_HTML (HTML_FRAME (self)->html)->iframe_parent)->engine;
287 		html_search_pop (info);
288 		html_engine_unselect_all (e);
289 		return html_search_next_parent (info);
290 	}
291 
292 	info->engine = e;
293 	html_search_push (info, e->clue);
294 	if (html_object_search (e->clue, info))
295 		return TRUE;
296 	html_search_pop (info);
297 
298 	info->engine = GTK_HTML (GTK_HTML (HTML_FRAME (self)->html)->iframe_parent)->engine;
299 	/* printf ("FALSE\n"); */
300 
301 	return FALSE;
302 }
303 
304 static HTMLObject *
head(HTMLObject * self)305 head (HTMLObject *self)
306 {
307 	return GTK_HTML (HTML_FRAME (self)->html)->engine->clue;
308 }
309 
310 static HTMLObject *
tail(HTMLObject * self)311 tail (HTMLObject *self)
312 {
313 	return GTK_HTML (HTML_FRAME (self)->html)->engine->clue;
314 }
315 
316 static HTMLEngine *
get_engine(HTMLObject * self,HTMLEngine * e)317 get_engine (HTMLObject *self,
318             HTMLEngine *e)
319 {
320 	return GTK_HTML (HTML_FRAME (self)->html)->engine;
321 }
322 
323 static HTMLObject *
check_point(HTMLObject * self,HTMLPainter * painter,gint x,gint y,guint * offset_return,gboolean for_cursor)324 check_point (HTMLObject *self,
325              HTMLPainter *painter,
326              gint x,
327              gint y,
328              guint *offset_return,
329              gboolean for_cursor)
330 {
331 	HTMLEngine *e = GTK_HTML (HTML_FRAME (self)->html)->engine;
332 
333 	if (x < self->x || x >= self->x + self->width
334 	    || y >= self->y + self->descent || y < self->y - self->ascent)
335 		return NULL;
336 
337 	x -= self->x + html_engine_get_left_border (e) - e->x_offset;
338 	y -= self->y - self->ascent + html_engine_get_top_border (e) - e->y_offset;
339 
340 	if (for_cursor && (x < 0 || y < e->clue->y - e->clue->ascent))
341 		return html_object_check_point (e->clue, e->painter, 0, e->clue->y - e->clue->ascent,
342 						offset_return, for_cursor);
343 
344 	if (for_cursor && (x > e->clue->width - 1 || y > e->clue->y + e->clue->descent - 1))
345 		return html_object_check_point (e->clue, e->painter, e->clue->width - 1, e->clue->y + e->clue->descent - 1,
346 						offset_return, for_cursor);
347 
348 	return html_object_check_point (e->clue, e->painter, x, y, offset_return, for_cursor);
349 }
350 
351 static gboolean
is_container(HTMLObject * self)352 is_container (HTMLObject *self)
353 {
354 	return TRUE;
355 }
356 
357 static void
append_selection_string(HTMLObject * self,GString * buffer)358 append_selection_string (HTMLObject *self,
359                          GString *buffer)
360 {
361 	html_object_append_selection_string (GTK_HTML (HTML_FRAME (self)->html)->engine->clue, buffer);
362 }
363 
364 static void
reparent(HTMLEmbedded * emb,GtkWidget * html)365 reparent (HTMLEmbedded *emb,
366           GtkWidget *html)
367 {
368 	HTMLFrame *frame = HTML_FRAME (emb);
369 
370 	gtk_html_set_iframe_parent (GTK_HTML (frame->html),
371 				    html,
372 				    GTK_HTML (frame->html)->frame);
373 	(* HTML_EMBEDDED_CLASS (parent_class)->reparent) (emb, html);
374 }
375 
376 static gboolean
select_range(HTMLObject * self,HTMLEngine * engine,guint start,gint length,gboolean queue_draw)377 select_range (HTMLObject *self,
378               HTMLEngine *engine,
379               guint start,
380               gint length,
381               gboolean queue_draw)
382 {
383 	return html_object_select_range (GTK_HTML (HTML_FRAME (self)->html)->engine->clue,
384 					 GTK_HTML (HTML_FRAME (self)->html)->engine,
385 					 start, length, queue_draw);
386 }
387 
388 static void
destroy(HTMLObject * o)389 destroy (HTMLObject *o)
390 {
391 	HTMLFrame *frame = HTML_FRAME (o);
392 
393 	frame_set_gdk_painter (frame, NULL);
394 
395 	if (frame->html) {
396 		g_signal_handlers_disconnect_matched (frame->html, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, o);
397 		frame->html = NULL;
398 	}
399 	g_free ((frame)->url);
400 
401 	HTML_OBJECT_CLASS (parent_class)->destroy (o);
402 }
403 
404 static HTMLAnchor *
find_anchor(HTMLObject * self,const gchar * name,gint * x,gint * y)405 find_anchor (HTMLObject *self,
406              const gchar *name,
407              gint *x,
408              gint *y)
409 {
410 	HTMLFrame *frame;
411 	HTMLAnchor *anchor;
412 
413 	g_return_val_if_fail (HTML_IS_FRAME (self), NULL);
414 
415 	frame = HTML_FRAME (self);
416 
417 	if (!frame || !frame->html || !GTK_IS_HTML (frame->html) || !GTK_HTML (frame->html)->engine || !GTK_HTML (frame->html)->engine->clue)
418 		return NULL;
419 
420 	anchor = html_object_find_anchor (GTK_HTML (frame->html)->engine->clue, name, x, y);
421 
422 	if (anchor) {
423 		*x += self->x;
424 		*y += self->y - self->ascent;
425 	}
426 
427 	return anchor;
428 }
429 
430 void
html_frame_set_margin_width(HTMLFrame * frame,gint margin_width)431 html_frame_set_margin_width (HTMLFrame *frame,
432                              gint margin_width)
433 {
434 	HTMLEngine *e;
435 
436 	e = GTK_HTML (frame->html)->engine;
437 
438 	e->leftBorder = e->rightBorder = margin_width;
439 	html_engine_schedule_redraw (e);
440 }
441 
442 void
html_frame_set_margin_height(HTMLFrame * frame,gint margin_height)443 html_frame_set_margin_height (HTMLFrame *frame,
444                               gint margin_height)
445 {
446 	HTMLEngine *e;
447 
448 	e = GTK_HTML (frame->html)->engine;
449 
450 	e->bottomBorder = e->topBorder = margin_height;
451 	html_engine_schedule_redraw (e);
452 }
453 
454 void
html_frame_set_scrolling(HTMLFrame * frame,GtkPolicyType scroll)455 html_frame_set_scrolling (HTMLFrame *frame,
456                           GtkPolicyType scroll)
457 {
458 
459 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (frame->scroll),
460 					scroll, scroll);
461 }
462 
463 void
html_frame_set_size(HTMLFrame * frame,gint width,gint height)464 html_frame_set_size (HTMLFrame *frame,
465                      gint width,
466                      gint height)
467 {
468 	g_return_if_fail (frame != NULL);
469 
470 	if (width > 0)
471 		frame->width = width;
472 
473 	if (height > 0)
474 		frame->height = height;
475 
476 	gtk_widget_set_size_request (frame->scroll, width, height);
477 }
478 
479 void
html_frame_init(HTMLFrame * frame,HTMLFrameClass * klass,GtkWidget * parent,gchar * src,gint width,gint height,gboolean border)480 html_frame_init (HTMLFrame *frame,
481                   HTMLFrameClass *klass,
482                   GtkWidget *parent,
483                   gchar *src,
484                   gint width,
485                   gint height,
486                   gboolean border)
487 {
488 	HTMLEmbedded *em = HTML_EMBEDDED (frame);
489 	HTMLTokenizer *new_tokenizer;
490 	GtkWidget *new_widget;
491 	GtkHTML   *new_html;
492 	GtkHTML   *parent_html;
493 	GtkWidget *scrolled_window;
494 
495 	g_assert (GTK_IS_HTML (parent));
496 	parent_html = GTK_HTML (parent);
497 
498 	html_embedded_init (em, HTML_EMBEDDED_CLASS (klass),
499 			    parent, NULL, NULL);
500 
501 	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
502 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
503 					     border ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
504 
505 	new_widget = gtk_html_new ();
506 	new_html = GTK_HTML (new_widget);
507 
508 	new_tokenizer = html_tokenizer_clone (parent_html->engine->ht);
509 
510 	html_engine_set_tokenizer (new_html->engine, new_tokenizer);
511 	g_object_unref (G_OBJECT (new_tokenizer));
512 	new_tokenizer = NULL;
513 
514 	gtk_html_set_default_content_type (new_html,
515 					   gtk_html_get_default_content_type (parent_html));
516 
517 	gtk_html_set_default_engine (new_html,
518 					   gtk_html_get_default_engine (parent_html));
519 
520 	frame->html = new_widget;
521 	frame->url = g_strdup (src);
522 	frame->width = width;
523 	frame->height = height;
524 	frame->gdk_painter = NULL;
525 	gtk_html_set_base (new_html, src);
526 	gtk_html_set_iframe_parent (new_html, parent, HTML_OBJECT (frame));
527 	gtk_container_add (GTK_CONTAINER (scrolled_window), new_widget);
528 	gtk_widget_show (new_widget);
529 
530 	g_signal_connect (new_html, "url_requested", G_CALLBACK (frame_url_requested), frame);
531 
532 	if (parent_html->engine->stopped) {
533 		gtk_html_stop (new_html);
534 		gtk_html_load_empty (new_html);
535 	} else {
536 		GtkHTMLStream *handle;
537 
538 		handle = gtk_html_begin (new_html);
539 		g_signal_emit_by_name (parent_html->engine, "url_requested", src, handle);
540 	}
541 
542 	new_html->engine->clue->parent = HTML_OBJECT (frame);
543 
544 #if 0
545 	/* NOTE: because of peculiarities of the frame/gtkhtml relationship
546 	 * on_url and link_clicked are emitted from the toplevel widget not
547 	 * proxied like url_requested is.
548 	 */
549 	g_signal_connect (new_html, "on_url", G_CALLBACK (frame_on_url), frame);
550 	g_signal_connect (new_html, "link_clicked", G_CALLBACK (frame_link_clicked), frame);
551 #endif
552 	g_signal_connect (new_html, "size_changed", G_CALLBACK (frame_size_changed), frame);
553 	g_signal_connect (new_html, "object_requested", G_CALLBACK (frame_object_requested), frame);
554 	g_signal_connect (new_html, "submit", G_CALLBACK (frame_submit), frame);
555 	g_signal_connect (new_html, "set_base", G_CALLBACK (frame_set_base), frame);
556 
557 	html_frame_set_margin_height (frame, 0);
558 	html_frame_set_margin_width (frame, 0);
559 
560 	/*
561 	  g_signal_connect (html, "button_press_event", G_CALLBACK (frame_button_press_event), frame);
562 	*/
563 
564 	gtk_widget_set_size_request (scrolled_window, width, height);
565 
566 	gtk_widget_show (scrolled_window);
567 	frame->scroll = scrolled_window;
568 	html_frame_set_scrolling (frame, GTK_POLICY_AUTOMATIC);
569 
570 	html_embedded_set_widget (em, scrolled_window);
571 
572 	g_signal_connect (scrolled_window, "button_press_event", G_CALLBACK (html_frame_grab_cursor), NULL);
573 
574 	/* inherit the current colors from our parent */
575 	html_colorset_set_unchanged (new_html->engine->defaultSettings->color_set,
576 				     parent_html->engine->settings->color_set);
577 	html_colorset_set_unchanged (new_html->engine->settings->color_set,
578 				     parent_html->engine->settings->color_set);
579 	html_painter_set_focus (new_html->engine->painter, parent_html->engine->have_focus);
580 	/*
581 	g_signal_connect (html, "title_changed", G_CALLBACK (title_changed_cb), app);
582 	g_signal_connect (html, "button_press_event", G_CALLBACK (on_button_press_event), popup_menu);
583 	g_signal_connect (html, "redirect", G_CALLBACK (on_redirect), NULL);
584 	g_signal_connect (html, "object_requested", G_CALLBACK (object_requested_cmd), NULL);
585 	*/
586 }
587 
588 void
html_frame_type_init(void)589 html_frame_type_init (void)
590 {
591 	html_frame_class_init (&html_frame_class, HTML_TYPE_FRAME, sizeof (HTMLFrame));
592 }
593 
594 void
html_frame_class_init(HTMLFrameClass * klass,HTMLType type,guint size)595 html_frame_class_init (HTMLFrameClass *klass,
596                         HTMLType type,
597                         guint size)
598 {
599 	HTMLEmbeddedClass *embedded_class;
600 	HTMLObjectClass  *object_class;
601 
602 	g_return_if_fail (klass != NULL);
603 
604 	embedded_class = HTML_EMBEDDED_CLASS (klass);
605 	object_class = HTML_OBJECT_CLASS (klass);
606 
607 	html_embedded_class_init (embedded_class, type, size);
608 	parent_class = &html_embedded_class;
609 
610 	object_class->destroy                 = destroy;
611 	object_class->calc_size               = html_frame_real_calc_size;
612 	object_class->calc_min_width          = calc_min_width;
613 	object_class->set_painter             = set_painter;
614 	/* object_class->reset                   = reset; */
615 	object_class->draw                    = draw;
616 	object_class->set_max_width           = set_max_width;
617 	object_class->forall                  = forall;
618 	object_class->check_page_split        = check_page_split;
619 	object_class->search                  = search;
620 	object_class->head                    = head;
621 	object_class->tail                    = tail;
622 	object_class->get_engine              = get_engine;
623 	object_class->check_point             = check_point;
624 	object_class->is_container            = is_container;
625 	object_class->append_selection_string = append_selection_string;
626 	object_class->select_range            = select_range;
627 	object_class->find_anchor             = find_anchor;
628 
629 	embedded_class->reparent = reparent;
630 }
631 
632