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 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 <ctype.h> |
---|
24 | |
---|
25 | #include <gdk/gdkkeysyms.h> |
---|
26 | #include <gdk/gdkprivate.h> |
---|
27 | #include <gdk-pixbuf/gdk-pixbuf.h> |
---|
28 | #include <gtk/gtk.h> |
---|
29 | #include <string.h> |
---|
30 | |
---|
31 | #include <gnome.h> |
---|
32 | |
---|
33 | #include "../a11y/factory.h" |
---|
34 | |
---|
35 | #include "htmlcolorset.h" |
---|
36 | #include "htmlcursor.h" |
---|
37 | #include "htmldrawqueue.h" |
---|
38 | #include "htmlengine-edit.h" |
---|
39 | #include "htmlengine-edit-clueflowstyle.h" |
---|
40 | #include "htmlengine-edit-cut-and-paste.h" |
---|
41 | #include "htmlengine-edit-fontstyle.h" |
---|
42 | #include "htmlengine-edit-rule.h" |
---|
43 | #include "htmlengine-edit-movement.h" |
---|
44 | #include "htmlengine-edit-cursor.h" |
---|
45 | #include "htmlengine-edit-table.h" |
---|
46 | #include "htmlengine-edit-tablecell.h" |
---|
47 | #include "htmlengine-edit-text.h" |
---|
48 | #include "htmlengine-edit-selection-updater.h" |
---|
49 | #include "htmlengine-print.h" |
---|
50 | #include "htmlengine-save.h" |
---|
51 | #include "htmlform.h" |
---|
52 | #include "htmlframe.h" |
---|
53 | #include "htmliframe.h" |
---|
54 | #include "htmlimage.h" |
---|
55 | #include "htmlinterval.h" |
---|
56 | #include "htmlmarshal.h" |
---|
57 | #include "htmlplainpainter.h" |
---|
58 | #include "htmlsettings.h" |
---|
59 | #include "htmltable.h" |
---|
60 | #include "htmltext.h" |
---|
61 | #include "htmltextslave.h" |
---|
62 | #include "htmlselection.h" |
---|
63 | #include "htmlundo.h" |
---|
64 | |
---|
65 | #include "gtkhtml.h" |
---|
66 | #include "gtkhtml-embedded.h" |
---|
67 | #include "gtkhtml-keybinding.h" |
---|
68 | #include "gtkhtml-search.h" |
---|
69 | #include "gtkhtml-stream.h" |
---|
70 | #include "gtkhtml-private.h" |
---|
71 | #include "gtkhtml-properties.h" |
---|
72 | #include "math.h" |
---|
73 | #include <libgnome/gnome-util.h> |
---|
74 | |
---|
75 | enum DndTargetType { |
---|
76 | DND_TARGET_TYPE_TEXT_URI_LIST, |
---|
77 | DND_TARGET_TYPE_MOZILLA_URL, |
---|
78 | DND_TARGET_TYPE_TEXT_HTML, |
---|
79 | DND_TARGET_TYPE_UTF8_STRING, |
---|
80 | DND_TARGET_TYPE_TEXT_PLAIN, |
---|
81 | DND_TARGET_TYPE_STRING, |
---|
82 | }; |
---|
83 | |
---|
84 | static GtkTargetEntry dnd_link_sources [] = { |
---|
85 | { "text/uri-list", 0, DND_TARGET_TYPE_TEXT_URI_LIST }, |
---|
86 | { "text/x-moz-url", 0, DND_TARGET_TYPE_MOZILLA_URL }, |
---|
87 | { "text/html", 0, DND_TARGET_TYPE_TEXT_HTML }, |
---|
88 | { "UTF8_STRING", 0, DND_TARGET_TYPE_UTF8_STRING }, |
---|
89 | { "text/plain", 0, DND_TARGET_TYPE_TEXT_PLAIN }, |
---|
90 | { "STRING", 0, DND_TARGET_TYPE_STRING }, |
---|
91 | }; |
---|
92 | #define DND_LINK_SOURCES sizeof (dnd_link_sources) / sizeof (GtkTargetEntry) |
---|
93 | |
---|
94 | #define GNOME_SPELL_GCONF_DIR "/GNOME/Spell" |
---|
95 | |
---|
96 | #define d_s(x) |
---|
97 | #define D_IM(x) |
---|
98 | |
---|
99 | static GtkLayoutClass *parent_class = NULL; |
---|
100 | |
---|
101 | GConfClient *gconf_client = NULL; |
---|
102 | GError *gconf_error = NULL; |
---|
103 | |
---|
104 | enum { |
---|
105 | TITLE_CHANGED, |
---|
106 | URL_REQUESTED, |
---|
107 | LOAD_DONE, |
---|
108 | LINK_CLICKED, |
---|
109 | SET_BASE, |
---|
110 | SET_BASE_TARGET, |
---|
111 | ON_URL, |
---|
112 | REDIRECT, |
---|
113 | SUBMIT, |
---|
114 | OBJECT_REQUESTED, |
---|
115 | CURRENT_PARAGRAPH_STYLE_CHANGED, |
---|
116 | CURRENT_PARAGRAPH_INDENTATION_CHANGED, |
---|
117 | CURRENT_PARAGRAPH_ALIGNMENT_CHANGED, |
---|
118 | INSERTION_FONT_STYLE_CHANGED, |
---|
119 | INSERTION_COLOR_CHANGED, |
---|
120 | SIZE_CHANGED, |
---|
121 | IFRAME_CREATED, |
---|
122 | /* keybindings signals */ |
---|
123 | SCROLL, |
---|
124 | CURSOR_MOVE, |
---|
125 | COMMAND, |
---|
126 | /* now only last signal */ |
---|
127 | LAST_SIGNAL |
---|
128 | }; |
---|
129 | |
---|
130 | /* #define USE_PROPS */ |
---|
131 | #ifdef USE_PROPS |
---|
132 | enum { |
---|
133 | PROP_0, |
---|
134 | PROP_EDITABLE, |
---|
135 | PROP_TITLE, |
---|
136 | PROP_DOCUMENT_BASE, |
---|
137 | PROP_TARGET_BASE, |
---|
138 | }; |
---|
139 | |
---|
140 | static void gtk_html_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); |
---|
141 | static void gtk_html_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); |
---|
142 | |
---|
143 | #endif |
---|
144 | |
---|
145 | static guint signals [LAST_SIGNAL] = { 0 }; |
---|
146 | |
---|
147 | static void |
---|
148 | gtk_html_update_scrollbars_on_resize (GtkHTML *html, |
---|
149 | gdouble old_doc_width, gdouble old_doc_height, |
---|
150 | gdouble old_width, gdouble old_height, |
---|
151 | gboolean *changed_x, gboolean *changed_y); |
---|
152 | |
---|
153 | /* keybindings signal hadlers */ |
---|
154 | static void scroll (GtkHTML *html, GtkOrientation orientation, GtkScrollType scroll_type, gfloat position); |
---|
155 | static void cursor_move (GtkHTML *html, GtkDirectionType dir_type, GtkHTMLCursorSkipType skip); |
---|
156 | static gboolean command (GtkHTML *html, GtkHTMLCommandType com_type); |
---|
157 | static gint mouse_change_pos (GtkWidget *widget, GdkWindow *window, gint x, gint y, gint state); |
---|
158 | static void add_bindings (GtkHTMLClass *klass); |
---|
159 | static gchar * get_value_nick (GtkHTMLCommandType com_type); |
---|
160 | |
---|
161 | |
---|
162 | /* Values for selection information. FIXME: what about COMPOUND_STRING and |
---|
163 | TEXT? */ |
---|
164 | enum _TargetInfo { |
---|
165 | TARGET_HTML, |
---|
166 | TARGET_UTF8_STRING, |
---|
167 | TARGET_UTF8, |
---|
168 | TARGET_COMPOUND_TEXT, |
---|
169 | TARGET_STRING, |
---|
170 | TARGET_TEXT |
---|
171 | }; |
---|
172 | |
---|
173 | typedef enum _TargetInfo TargetInfo; |
---|
174 | |
---|
175 | /* Interval for scrolling during selection. */ |
---|
176 | #define SCROLL_TIMEOUT_INTERVAL 10 |
---|
177 | |
---|
178 | |
---|
179 | GtkHTMLParagraphStyle |
---|
180 | clueflow_style_to_paragraph_style (HTMLClueFlowStyle style, HTMLListType item_type) |
---|
181 | { |
---|
182 | switch (style) { |
---|
183 | case HTML_CLUEFLOW_STYLE_NORMAL: |
---|
184 | return GTK_HTML_PARAGRAPH_STYLE_NORMAL; |
---|
185 | case HTML_CLUEFLOW_STYLE_H1: |
---|
186 | return GTK_HTML_PARAGRAPH_STYLE_H1; |
---|
187 | case HTML_CLUEFLOW_STYLE_H2: |
---|
188 | return GTK_HTML_PARAGRAPH_STYLE_H2; |
---|
189 | case HTML_CLUEFLOW_STYLE_H3: |
---|
190 | return GTK_HTML_PARAGRAPH_STYLE_H3; |
---|
191 | case HTML_CLUEFLOW_STYLE_H4: |
---|
192 | return GTK_HTML_PARAGRAPH_STYLE_H4; |
---|
193 | case HTML_CLUEFLOW_STYLE_H5: |
---|
194 | return GTK_HTML_PARAGRAPH_STYLE_H5; |
---|
195 | case HTML_CLUEFLOW_STYLE_H6: |
---|
196 | return GTK_HTML_PARAGRAPH_STYLE_H6; |
---|
197 | case HTML_CLUEFLOW_STYLE_ADDRESS: |
---|
198 | return GTK_HTML_PARAGRAPH_STYLE_ADDRESS; |
---|
199 | case HTML_CLUEFLOW_STYLE_PRE: |
---|
200 | return GTK_HTML_PARAGRAPH_STYLE_PRE; |
---|
201 | case HTML_CLUEFLOW_STYLE_LIST_ITEM: |
---|
202 | switch (item_type) { |
---|
203 | case HTML_LIST_TYPE_UNORDERED: |
---|
204 | return GTK_HTML_PARAGRAPH_STYLE_ITEMDOTTED; |
---|
205 | case HTML_LIST_TYPE_ORDERED_ARABIC: |
---|
206 | return GTK_HTML_PARAGRAPH_STYLE_ITEMDIGIT; |
---|
207 | case HTML_LIST_TYPE_ORDERED_LOWER_ROMAN: |
---|
208 | case HTML_LIST_TYPE_ORDERED_UPPER_ROMAN: |
---|
209 | return GTK_HTML_PARAGRAPH_STYLE_ITEMROMAN; |
---|
210 | case HTML_LIST_TYPE_ORDERED_LOWER_ALPHA: |
---|
211 | case HTML_LIST_TYPE_ORDERED_UPPER_ALPHA: |
---|
212 | return GTK_HTML_PARAGRAPH_STYLE_ITEMALPHA; |
---|
213 | default: |
---|
214 | return GTK_HTML_PARAGRAPH_STYLE_ITEMDOTTED; |
---|
215 | } |
---|
216 | default: /* This should not really happen, though. */ |
---|
217 | return GTK_HTML_PARAGRAPH_STYLE_NORMAL; |
---|
218 | } |
---|
219 | } |
---|
220 | |
---|
221 | void |
---|
222 | paragraph_style_to_clueflow_style (GtkHTMLParagraphStyle style, HTMLClueFlowStyle *flow_style, HTMLListType *item_type) |
---|
223 | { |
---|
224 | *item_type = HTML_LIST_TYPE_BLOCKQUOTE; |
---|
225 | *flow_style = HTML_CLUEFLOW_STYLE_LIST_ITEM; |
---|
226 | |
---|
227 | switch (style) { |
---|
228 | case GTK_HTML_PARAGRAPH_STYLE_NORMAL: |
---|
229 | *flow_style = HTML_CLUEFLOW_STYLE_NORMAL; |
---|
230 | break; |
---|
231 | case GTK_HTML_PARAGRAPH_STYLE_H1: |
---|
232 | *flow_style = HTML_CLUEFLOW_STYLE_H1; |
---|
233 | break; |
---|
234 | case GTK_HTML_PARAGRAPH_STYLE_H2: |
---|
235 | *flow_style = HTML_CLUEFLOW_STYLE_H2; |
---|
236 | break; |
---|
237 | case GTK_HTML_PARAGRAPH_STYLE_H3: |
---|
238 | *flow_style = HTML_CLUEFLOW_STYLE_H3; |
---|
239 | break; |
---|
240 | case GTK_HTML_PARAGRAPH_STYLE_H4: |
---|
241 | *flow_style = HTML_CLUEFLOW_STYLE_H4; |
---|
242 | break; |
---|
243 | case GTK_HTML_PARAGRAPH_STYLE_H5: |
---|
244 | *flow_style = HTML_CLUEFLOW_STYLE_H5; |
---|
245 | break; |
---|
246 | case GTK_HTML_PARAGRAPH_STYLE_H6: |
---|
247 | *flow_style = HTML_CLUEFLOW_STYLE_H6; |
---|
248 | break; |
---|
249 | case GTK_HTML_PARAGRAPH_STYLE_ADDRESS: |
---|
250 | *flow_style = HTML_CLUEFLOW_STYLE_ADDRESS; |
---|
251 | break; |
---|
252 | case GTK_HTML_PARAGRAPH_STYLE_PRE: |
---|
253 | *flow_style = HTML_CLUEFLOW_STYLE_PRE; |
---|
254 | break; |
---|
255 | case GTK_HTML_PARAGRAPH_STYLE_ITEMDOTTED: |
---|
256 | *item_type = HTML_LIST_TYPE_UNORDERED; |
---|
257 | break; |
---|
258 | case GTK_HTML_PARAGRAPH_STYLE_ITEMROMAN: |
---|
259 | *item_type = HTML_LIST_TYPE_ORDERED_UPPER_ROMAN; |
---|
260 | break; |
---|
261 | case GTK_HTML_PARAGRAPH_STYLE_ITEMALPHA: |
---|
262 | *item_type = HTML_LIST_TYPE_ORDERED_UPPER_ALPHA; |
---|
263 | break; |
---|
264 | case GTK_HTML_PARAGRAPH_STYLE_ITEMDIGIT: |
---|
265 | *item_type = HTML_LIST_TYPE_ORDERED_ARABIC; |
---|
266 | break; |
---|
267 | default: /* This should not really happen, though. */ |
---|
268 | *flow_style = HTML_CLUEFLOW_STYLE_NORMAL; |
---|
269 | } |
---|
270 | } |
---|
271 | |
---|
272 | HTMLHAlignType |
---|
273 | paragraph_alignment_to_html (GtkHTMLParagraphAlignment alignment) |
---|
274 | { |
---|
275 | switch (alignment) { |
---|
276 | case GTK_HTML_PARAGRAPH_ALIGNMENT_LEFT: |
---|
277 | return HTML_HALIGN_LEFT; |
---|
278 | case GTK_HTML_PARAGRAPH_ALIGNMENT_RIGHT: |
---|
279 | return HTML_HALIGN_RIGHT; |
---|
280 | case GTK_HTML_PARAGRAPH_ALIGNMENT_CENTER: |
---|
281 | return HTML_HALIGN_CENTER; |
---|
282 | default: |
---|
283 | return HTML_HALIGN_LEFT; |
---|
284 | } |
---|
285 | } |
---|
286 | |
---|
287 | GtkHTMLParagraphAlignment |
---|
288 | html_alignment_to_paragraph (HTMLHAlignType alignment) |
---|
289 | { |
---|
290 | switch (alignment) { |
---|
291 | case HTML_HALIGN_LEFT: |
---|
292 | return GTK_HTML_PARAGRAPH_ALIGNMENT_LEFT; |
---|
293 | case HTML_HALIGN_CENTER: |
---|
294 | return GTK_HTML_PARAGRAPH_ALIGNMENT_CENTER; |
---|
295 | case HTML_HALIGN_RIGHT: |
---|
296 | return GTK_HTML_PARAGRAPH_ALIGNMENT_RIGHT; |
---|
297 | default: |
---|
298 | return GTK_HTML_PARAGRAPH_ALIGNMENT_LEFT; |
---|
299 | } |
---|
300 | } |
---|
301 | |
---|
302 | void |
---|
303 | gtk_html_update_styles (GtkHTML *html) |
---|
304 | { |
---|
305 | GtkHTMLParagraphStyle paragraph_style; |
---|
306 | GtkHTMLParagraphAlignment alignment; |
---|
307 | HTMLEngine *engine; |
---|
308 | HTMLClueFlowStyle flow_style; |
---|
309 | HTMLListType item_type; |
---|
310 | guint indentation; |
---|
311 | |
---|
312 | /* printf ("gtk_html_update_styles called\n"); */ |
---|
313 | |
---|
314 | if (! html_engine_get_editable (html->engine)) |
---|
315 | return; |
---|
316 | |
---|
317 | engine = html->engine; |
---|
318 | html_engine_get_current_clueflow_style (engine, &flow_style, &item_type); |
---|
319 | paragraph_style = clueflow_style_to_paragraph_style (flow_style, item_type); |
---|
320 | |
---|
321 | if (paragraph_style != html->priv->paragraph_style) { |
---|
322 | html->priv->paragraph_style = paragraph_style; |
---|
323 | g_signal_emit (html, signals [CURRENT_PARAGRAPH_STYLE_CHANGED], 0, paragraph_style); |
---|
324 | } |
---|
325 | |
---|
326 | indentation = html_engine_get_current_clueflow_indentation (engine); |
---|
327 | if (indentation != html->priv->paragraph_indentation) { |
---|
328 | html->priv->paragraph_indentation = indentation; |
---|
329 | g_signal_emit (html, signals [CURRENT_PARAGRAPH_INDENTATION_CHANGED], 0, indentation); |
---|
330 | } |
---|
331 | |
---|
332 | alignment = html_alignment_to_paragraph (html_engine_get_current_clueflow_alignment (engine)); |
---|
333 | if (alignment != html->priv->paragraph_alignment) { |
---|
334 | html->priv->paragraph_alignment = alignment; |
---|
335 | g_signal_emit (html, signals [CURRENT_PARAGRAPH_ALIGNMENT_CHANGED], 0, alignment); |
---|
336 | } |
---|
337 | |
---|
338 | if (html_engine_update_insertion_font_style (engine)) |
---|
339 | g_signal_emit (html, signals [INSERTION_FONT_STYLE_CHANGED], 0, engine->insertion_font_style); |
---|
340 | if (html_engine_update_insertion_color (engine)) |
---|
341 | g_signal_emit (html, signals [INSERTION_COLOR_CHANGED], 0, engine->insertion_color); |
---|
342 | |
---|
343 | /* TODO add insertion_url_or_targed_changed signal */ |
---|
344 | html_engine_update_insertion_url_and_target (engine); |
---|
345 | } |
---|
346 | |
---|
347 | |
---|
348 | /* GTK+ idle loop handler. */ |
---|
349 | |
---|
350 | static gint |
---|
351 | idle_handler (gpointer data) |
---|
352 | { |
---|
353 | GtkHTML *html; |
---|
354 | HTMLEngine *engine; |
---|
355 | |
---|
356 | html = GTK_HTML (data); |
---|
357 | engine = html->engine; |
---|
358 | |
---|
359 | if (html->priv->scroll_timeout_id == 0 && |
---|
360 | html->engine->thaw_idle_id == 0 && |
---|
361 | !html_engine_frozen (html->engine)) |
---|
362 | html_engine_make_cursor_visible (engine); |
---|
363 | |
---|
364 | if (html->engine->thaw_idle_id == 0 && !html_engine_frozen (html->engine)) |
---|
365 | html_engine_flush_draw_queue (engine); |
---|
366 | |
---|
367 | gtk_adjustment_set_value (GTK_LAYOUT (html)->hadjustment, (gfloat) engine->x_offset); |
---|
368 | gtk_adjustment_set_value (GTK_LAYOUT (html)->vadjustment, (gfloat) engine->y_offset); |
---|
369 | |
---|
370 | gtk_html_private_calc_scrollbars (html, NULL, NULL); |
---|
371 | |
---|
372 | html->priv->idle_handler_id = 0; |
---|
373 | return FALSE; |
---|
374 | } |
---|
375 | |
---|
376 | static void |
---|
377 | queue_draw (GtkHTML *html) |
---|
378 | { |
---|
379 | if (html->priv->idle_handler_id == 0) |
---|
380 | html->priv->idle_handler_id = gtk_idle_add (idle_handler, html); |
---|
381 | } |
---|
382 | |
---|
383 | |
---|
384 | /* HTMLEngine callbacks. */ |
---|
385 | |
---|
386 | static void |
---|
387 | html_engine_title_changed_cb (HTMLEngine *engine, gpointer data) |
---|
388 | { |
---|
389 | GtkHTML *gtk_html; |
---|
390 | |
---|
391 | gtk_html = GTK_HTML (data); |
---|
392 | g_signal_emit (gtk_html, signals [TITLE_CHANGED], 0, engine->title->str); |
---|
393 | } |
---|
394 | |
---|
395 | static void |
---|
396 | html_engine_set_base_cb (HTMLEngine *engine, const gchar *base, gpointer data) |
---|
397 | { |
---|
398 | GtkHTML *gtk_html; |
---|
399 | |
---|
400 | gtk_html = GTK_HTML (data); |
---|
401 | gtk_html_set_base (gtk_html, base); |
---|
402 | g_signal_emit (gtk_html, signals[SET_BASE], 0, base); |
---|
403 | } |
---|
404 | |
---|
405 | static void |
---|
406 | html_engine_set_base_target_cb (HTMLEngine *engine, const gchar *base_target, gpointer data) |
---|
407 | { |
---|
408 | GtkHTML *gtk_html; |
---|
409 | |
---|
410 | gtk_html = GTK_HTML (data); |
---|
411 | g_signal_emit (gtk_html, signals[SET_BASE_TARGET], 0, base_target); |
---|
412 | } |
---|
413 | |
---|
414 | static void |
---|
415 | html_engine_load_done_cb (HTMLEngine *engine, gpointer data) |
---|
416 | { |
---|
417 | GtkHTML *gtk_html; |
---|
418 | |
---|
419 | gtk_html = GTK_HTML (data); |
---|
420 | g_signal_emit (gtk_html, signals[LOAD_DONE], 0); |
---|
421 | } |
---|
422 | |
---|
423 | static void |
---|
424 | html_engine_url_requested_cb (HTMLEngine *engine, |
---|
425 | const gchar *url, |
---|
426 | GtkHTMLStream *handle, |
---|
427 | gpointer data) |
---|
428 | { |
---|
429 | GtkHTML *gtk_html; |
---|
430 | char *expanded = NULL; |
---|
431 | gtk_html = GTK_HTML (data); |
---|
432 | |
---|
433 | if (engine->stopped) |
---|
434 | return; |
---|
435 | |
---|
436 | expanded = gtk_html_get_url_base_relative (gtk_html, url); |
---|
437 | g_signal_emit (gtk_html, signals[URL_REQUESTED], 0, expanded, handle); |
---|
438 | g_free (expanded); |
---|
439 | } |
---|
440 | |
---|
441 | static void |
---|
442 | html_engine_draw_pending_cb (HTMLEngine *engine, |
---|
443 | gpointer data) |
---|
444 | { |
---|
445 | GtkHTML *html; |
---|
446 | |
---|
447 | html = GTK_HTML (data); |
---|
448 | queue_draw (html); |
---|
449 | } |
---|
450 | |
---|
451 | static void |
---|
452 | html_engine_redirect_cb (HTMLEngine *engine, |
---|
453 | const gchar *url, |
---|
454 | int delay, |
---|
455 | gpointer data) |
---|
456 | { |
---|
457 | GtkHTML *gtk_html; |
---|
458 | |
---|
459 | gtk_html = GTK_HTML (data); |
---|
460 | |
---|
461 | g_signal_emit (gtk_html, signals[REDIRECT], 0, url, delay); |
---|
462 | } |
---|
463 | |
---|
464 | static void |
---|
465 | html_engine_submit_cb (HTMLEngine *engine, |
---|
466 | const gchar *method, |
---|
467 | const gchar *url, |
---|
468 | const gchar *encoding, |
---|
469 | gpointer data) |
---|
470 | { |
---|
471 | GtkHTML *gtk_html; |
---|
472 | |
---|
473 | gtk_html = GTK_HTML (data); |
---|
474 | |
---|
475 | g_signal_emit (gtk_html, signals[SUBMIT], 0, method, url, encoding); |
---|
476 | } |
---|
477 | |
---|
478 | static gboolean |
---|
479 | html_engine_object_requested_cb (HTMLEngine *engine, |
---|
480 | GtkHTMLEmbedded *eb, |
---|
481 | gpointer data) |
---|
482 | { |
---|
483 | GtkHTML *gtk_html; |
---|
484 | gboolean object_found = FALSE; |
---|
485 | |
---|
486 | gtk_html = GTK_HTML (data); |
---|
487 | |
---|
488 | object_found = FALSE; |
---|
489 | g_signal_emit (gtk_html, signals[OBJECT_REQUESTED], 0, eb, &object_found); |
---|
490 | return object_found; |
---|
491 | } |
---|
492 | |
---|
493 | |
---|
494 | /* GtkAdjustment handling. */ |
---|
495 | |
---|
496 | static void |
---|
497 | scroll_update_mouse (GtkWidget *widget) |
---|
498 | { |
---|
499 | gint x, y; |
---|
500 | |
---|
501 | if (GTK_WIDGET_REALIZED (widget)) { |
---|
502 | gdk_window_get_pointer (GTK_LAYOUT (widget)->bin_window, &x, &y, NULL); |
---|
503 | mouse_change_pos (widget, widget->window, x, y, 0); |
---|
504 | } |
---|
505 | } |
---|
506 | |
---|
507 | static void |
---|
508 | vertical_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
---|
509 | { |
---|
510 | GtkHTML *html = GTK_HTML (data); |
---|
511 | |
---|
512 | /* check if adjustment is valid, it's changed in |
---|
513 | Layout::size_allocate and we can't do anything about it, |
---|
514 | because it uses private fields we cannot access, so we have |
---|
515 | to use it*/ |
---|
516 | if (html->engine->height != adjustment->page_increment) |
---|
517 | return; |
---|
518 | |
---|
519 | html->engine->y_offset = (gint) adjustment->value; |
---|
520 | scroll_update_mouse (GTK_WIDGET (data)); |
---|
521 | } |
---|
522 | |
---|
523 | static void |
---|
524 | horizontal_scroll_cb (GtkAdjustment *adjustment, gpointer data) |
---|
525 | { |
---|
526 | GtkHTML *html = GTK_HTML (data); |
---|
527 | |
---|
528 | /* check if adjustment is valid, it's changed in |
---|
529 | Layout::size_allocate and we can't do anything about it, |
---|
530 | because it uses private fields we cannot access, so we have |
---|
531 | to use it*/ |
---|
532 | if (html->engine->width != adjustment->page_increment) |
---|
533 | return; |
---|
534 | |
---|
535 | html->engine->x_offset = (gint) adjustment->value; |
---|
536 | scroll_update_mouse (GTK_WIDGET (data)); |
---|
537 | } |
---|
538 | |
---|
539 | static void |
---|
540 | connect_adjustments (GtkHTML *html, |
---|
541 | GtkAdjustment *hadj, |
---|
542 | GtkAdjustment *vadj) |
---|
543 | { |
---|
544 | GtkLayout *layout; |
---|
545 | |
---|
546 | layout = GTK_LAYOUT (html); |
---|
547 | |
---|
548 | if (html->hadj_connection != 0) |
---|
549 | g_signal_handler_disconnect (layout->hadjustment, html->hadj_connection); |
---|
550 | |
---|
551 | if (html->vadj_connection != 0) |
---|
552 | g_signal_handler_disconnect (layout->vadjustment, html->vadj_connection); |
---|
553 | |
---|
554 | if (vadj != NULL) |
---|
555 | html->vadj_connection = |
---|
556 | g_signal_connect (vadj, "value_changed", G_CALLBACK (vertical_scroll_cb), (gpointer) html); |
---|
557 | else |
---|
558 | html->vadj_connection = 0; |
---|
559 | |
---|
560 | if (hadj != NULL) |
---|
561 | html->hadj_connection = |
---|
562 | g_signal_connect (hadj, "value_changed", G_CALLBACK (horizontal_scroll_cb), (gpointer) html); |
---|
563 | else |
---|
564 | html->hadj_connection = 0; |
---|
565 | } |
---|
566 | |
---|
567 | |
---|
568 | /* Scroll timeout handling. */ |
---|
569 | |
---|
570 | static void |
---|
571 | inc_adjustment (GtkAdjustment *adj, gint doc_width, gint alloc_width, gint inc) |
---|
572 | { |
---|
573 | gfloat value; |
---|
574 | gint max; |
---|
575 | |
---|
576 | value = adj->value + (gfloat) inc; |
---|
577 | |
---|
578 | if (doc_width > alloc_width) |
---|
579 | max = doc_width - alloc_width; |
---|
580 | else |
---|
581 | max = 0; |
---|
582 | |
---|
583 | if (value > (gfloat) max) |
---|
584 | value = (gfloat) max; |
---|
585 | else if (value < 0) |
---|
586 | value = 0.0; |
---|
587 | |
---|
588 | gtk_adjustment_set_value (adj, value); |
---|
589 | } |
---|
590 | |
---|
591 | static gint |
---|
592 | scroll_timeout_cb (gpointer data) |
---|
593 | { |
---|
594 | GtkWidget *widget; |
---|
595 | GtkHTML *html; |
---|
596 | HTMLEngine *engine; |
---|
597 | |
---|
598 | GtkLayout *layout; |
---|
599 | gint x_scroll, y_scroll; |
---|
600 | gint x, y; |
---|
601 | |
---|
602 | GDK_THREADS_ENTER (); |
---|
603 | |
---|
604 | widget = GTK_WIDGET (data); |
---|
605 | html = GTK_HTML (data); |
---|
606 | engine = html->engine; |
---|
607 | |
---|
608 | gdk_window_get_pointer (widget->window, &x, &y, NULL); |
---|
609 | |
---|
610 | if (x < 0) { |
---|
611 | x_scroll = x; |
---|
612 | if (x + engine->x_offset >= 0) |
---|
613 | x = 0; |
---|
614 | } else if (x >= widget->allocation.width) { |
---|
615 | x_scroll = x - widget->allocation.width + 1; |
---|
616 | x = widget->allocation.width; |
---|
617 | } else { |
---|
618 | x_scroll = 0; |
---|
619 | } |
---|
620 | x_scroll /= 2; |
---|
621 | |
---|
622 | if (y < 0) { |
---|
623 | y_scroll = y; |
---|
624 | if (y + engine->y_offset >= 0) |
---|
625 | y = 0; |
---|
626 | } else if (y >= widget->allocation.height) { |
---|
627 | y_scroll = y - widget->allocation.height + 1; |
---|
628 | y = widget->allocation.height; |
---|
629 | } else { |
---|
630 | y_scroll = 0; |
---|
631 | } |
---|
632 | y_scroll /= 2; |
---|
633 | |
---|
634 | if (html->in_selection && (x_scroll != 0 || y_scroll != 0)) |
---|
635 | html_engine_select_region (engine, html->selection_x1, html->selection_y1, |
---|
636 | x + engine->x_offset, y + engine->y_offset); |
---|
637 | |
---|
638 | layout = GTK_LAYOUT (widget); |
---|
639 | |
---|
640 | inc_adjustment (layout->hadjustment, html_engine_get_doc_width (html->engine), |
---|
641 | widget->allocation.width, x_scroll); |
---|
642 | inc_adjustment (layout->vadjustment, html_engine_get_doc_height (html->engine), |
---|
643 | widget->allocation.height, y_scroll); |
---|
644 | |
---|
645 | GDK_THREADS_LEAVE (); |
---|
646 | |
---|
647 | return TRUE; |
---|
648 | } |
---|
649 | |
---|
650 | static void |
---|
651 | setup_scroll_timeout (GtkHTML *html) |
---|
652 | { |
---|
653 | if (html->priv->scroll_timeout_id != 0) |
---|
654 | return; |
---|
655 | |
---|
656 | html->priv->scroll_timeout_id = gtk_timeout_add (SCROLL_TIMEOUT_INTERVAL, |
---|
657 | scroll_timeout_cb, html); |
---|
658 | |
---|
659 | GDK_THREADS_LEAVE(); |
---|
660 | scroll_timeout_cb (html); |
---|
661 | GDK_THREADS_ENTER(); |
---|
662 | } |
---|
663 | |
---|
664 | static void |
---|
665 | remove_scroll_timeout (GtkHTML *html) |
---|
666 | { |
---|
667 | if (html->priv->scroll_timeout_id == 0) |
---|
668 | return; |
---|
669 | |
---|
670 | gtk_timeout_remove (html->priv->scroll_timeout_id); |
---|
671 | html->priv->scroll_timeout_id = 0; |
---|
672 | } |
---|
673 | |
---|
674 | |
---|
675 | /* GtkObject methods. */ |
---|
676 | |
---|
677 | static void |
---|
678 | destroy (GtkObject *object) |
---|
679 | { |
---|
680 | GtkHTML *html; |
---|
681 | |
---|
682 | html = GTK_HTML (object); |
---|
683 | |
---|
684 | g_free (html->pointer_url); |
---|
685 | html->pointer_url = NULL; |
---|
686 | |
---|
687 | if (html->hand_cursor) { |
---|
688 | gdk_cursor_unref (html->hand_cursor); |
---|
689 | html->hand_cursor = NULL; |
---|
690 | } |
---|
691 | |
---|
692 | if (html->ibeam_cursor) { |
---|
693 | gdk_cursor_unref (html->ibeam_cursor); |
---|
694 | html->ibeam_cursor = NULL; |
---|
695 | } |
---|
696 | |
---|
697 | connect_adjustments (html, NULL, NULL); |
---|
698 | |
---|
699 | if (html->priv) { |
---|
700 | if (html->priv->idle_handler_id != 0) { |
---|
701 | gtk_idle_remove (html->priv->idle_handler_id); |
---|
702 | html->priv->idle_handler_id = 0; |
---|
703 | } |
---|
704 | |
---|
705 | if (html->priv->scroll_timeout_id != 0) { |
---|
706 | gtk_timeout_remove (html->priv->scroll_timeout_id); |
---|
707 | html->priv->scroll_timeout_id = 0; |
---|
708 | } |
---|
709 | |
---|
710 | if (html->priv->notify_spell_id) { |
---|
711 | gconf_client_notify_remove (gconf_client, html->priv->notify_spell_id); |
---|
712 | html->priv->notify_spell_id = 0; |
---|
713 | } |
---|
714 | |
---|
715 | if (html->priv->notify_monospace_font_id) { |
---|
716 | gconf_client_notify_remove (gconf_client, html->priv->notify_monospace_font_id); |
---|
717 | html->priv->notify_monospace_font_id = 0; |
---|
718 | } |
---|
719 | |
---|
720 | if (html->priv->resize_cursor) { |
---|
721 | gdk_cursor_unref (html->priv->resize_cursor); |
---|
722 | html->priv->resize_cursor = NULL; |
---|
723 | } |
---|
724 | |
---|
725 | g_free (html->priv->content_type); |
---|
726 | g_free (html->priv->base_url); |
---|
727 | g_free (html->priv); |
---|
728 | html->priv = NULL; |
---|
729 | } |
---|
730 | |
---|
731 | if (html->engine) { |
---|
732 | g_object_unref (G_OBJECT (html->engine)); |
---|
733 | html->engine = NULL; |
---|
734 | } |
---|
735 | |
---|
736 | if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL) |
---|
737 | (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); |
---|
738 | } |
---|
739 | |
---|
740 | GtkHTML * |
---|
741 | gtk_html_get_top_html (GtkHTML *html) |
---|
742 | { |
---|
743 | while (html->iframe_parent) |
---|
744 | html = GTK_HTML (html->iframe_parent); |
---|
745 | |
---|
746 | return html; |
---|
747 | } |
---|
748 | |
---|
749 | void |
---|
750 | gtk_html_set_fonts (GtkHTML *html, HTMLPainter *painter) |
---|
751 | { |
---|
752 | GtkWidget *top_level; |
---|
753 | GtkStyle *style; |
---|
754 | PangoFontDescription *fixed_desc = NULL; |
---|
755 | char *fixed_name = NULL; |
---|
756 | const char *fixed_family = NULL; |
---|
757 | gint fixed_size = 0; |
---|
758 | const char *font_var = NULL; |
---|
759 | gint font_var_size = 0; |
---|
760 | |
---|
761 | top_level = GTK_WIDGET (gtk_html_get_top_html (html)); |
---|
762 | style = gtk_widget_get_style (top_level); |
---|
763 | |
---|
764 | font_var = pango_font_description_get_family (style->font_desc); |
---|
765 | font_var_size = pango_font_description_get_size (style->font_desc); |
---|
766 | |
---|
767 | gtk_widget_style_get (GTK_WIDGET (top_level), "fixed_font_name", &fixed_name, NULL); |
---|
768 | if (fixed_name) { |
---|
769 | fixed_desc = pango_font_description_from_string (fixed_name); |
---|
770 | if (pango_font_description_get_family (fixed_desc)) { |
---|
771 | fixed_size = pango_font_description_get_size (fixed_desc); |
---|
772 | fixed_family = pango_font_description_get_family (fixed_desc); |
---|
773 | } else { |
---|
774 | g_free (fixed_name); |
---|
775 | fixed_name = NULL; |
---|
776 | } |
---|
777 | } |
---|
778 | |
---|
779 | if (!fixed_name) { |
---|
780 | GConfClient *gconf; |
---|
781 | |
---|
782 | gconf = gconf_client_get_default (); |
---|
783 | fixed_name = gconf_client_get_string (gconf, "/desktop/gnome/interface/monospace_font_name", NULL); |
---|
784 | if (fixed_name) { |
---|
785 | fixed_desc = pango_font_description_from_string (fixed_name); |
---|
786 | if (fixed_desc) { |
---|
787 | fixed_size = pango_font_description_get_size (fixed_desc); |
---|
788 | fixed_family = pango_font_description_get_family (fixed_desc); |
---|
789 | } else { |
---|
790 | g_free (fixed_name); |
---|
791 | fixed_name = NULL; |
---|
792 | } |
---|
793 | } |
---|
794 | g_object_unref (gconf); |
---|
795 | } |
---|
796 | |
---|
797 | if (!fixed_name) { |
---|
798 | fixed_family = "Monospace"; |
---|
799 | fixed_size = font_var_size; |
---|
800 | } |
---|
801 | |
---|
802 | html_font_manager_set_default (&painter->font_manager, |
---|
803 | (char *)font_var, (char *)fixed_family, |
---|
804 | font_var_size, FALSE, |
---|
805 | fixed_size, FALSE); |
---|
806 | if (fixed_desc) |
---|
807 | pango_font_description_free (fixed_desc); |
---|
808 | |
---|
809 | g_free (fixed_name); |
---|
810 | } |
---|
811 | |
---|
812 | static void |
---|
813 | set_caret_mode(HTMLEngine *engine, gboolean caret_mode) |
---|
814 | { |
---|
815 | if (engine->editable) |
---|
816 | return; |
---|
817 | |
---|
818 | if (!caret_mode && engine->blinking_timer_id) |
---|
819 | html_engine_stop_blinking_cursor (engine); |
---|
820 | |
---|
821 | engine->caret_mode = caret_mode; |
---|
822 | |
---|
823 | if (caret_mode && !engine->parsing && !engine->timerId == 0) |
---|
824 | gtk_html_edit_make_cursor_visible(engine->widget); |
---|
825 | |
---|
826 | /* Normally, blink cursor handler is setup in focus in event. |
---|
827 | * However, in the case focus already in this engine, and user |
---|
828 | * type F7 to enable cursor, we must setup the handler by |
---|
829 | * ourselves. |
---|
830 | */ |
---|
831 | if (caret_mode && !engine->blinking_timer_id && engine->have_focus) |
---|
832 | html_engine_setup_blinking_cursor (engine); |
---|
833 | |
---|
834 | return; |
---|
835 | } |
---|
836 | |
---|
837 | /* GtkWidget methods. */ |
---|
838 | static void |
---|
839 | style_set (GtkWidget *widget, GtkStyle *previous_style) |
---|
840 | { |
---|
841 | HTMLEngine *engine = GTK_HTML (widget)->engine; |
---|
842 | |
---|
843 | /* we don't need to set font's in idle time so call idle callback directly to avoid |
---|
844 | recalculating whole document |
---|
845 | */ |
---|
846 | if (engine) { |
---|
847 | gtk_html_set_fonts (GTK_HTML (widget), engine->painter); |
---|
848 | html_engine_refresh_fonts (engine); |
---|
849 | } |
---|
850 | |
---|
851 | |
---|
852 | html_colorset_set_style (engine->defaultSettings->color_set, widget); |
---|
853 | html_colorset_set_unchanged (engine->settings->color_set, |
---|
854 | engine->defaultSettings->color_set); |
---|
855 | |
---|
856 | /* link and quotation colors might changed => need to refresh pango info in text objects */ |
---|
857 | if (engine->clue) |
---|
858 | html_object_change_set_down (engine->clue, HTML_CHANGE_RECALC_PI); |
---|
859 | html_engine_schedule_update (engine); |
---|
860 | } |
---|
861 | |
---|
862 | static gint |
---|
863 | key_press_event (GtkWidget *widget, GdkEventKey *event) |
---|
864 | { |
---|
865 | GtkHTML *html = GTK_HTML (widget); |
---|
866 | GtkHTMLClass *html_class = GTK_HTML_CLASS (GTK_WIDGET_GET_CLASS (html)); |
---|
867 | gboolean retval, update = TRUE; |
---|
868 | |
---|
869 | html->binding_handled = FALSE; |
---|
870 | html->priv->update_styles = FALSE; |
---|
871 | html->priv->event_time = event->time; |
---|
872 | |
---|
873 | if (html_engine_get_editable (html->engine)) { |
---|
874 | if (gtk_im_context_filter_keypress (html->priv->im_context, event)) { |
---|
875 | html_engine_reset_blinking_cursor (html->engine); |
---|
876 | html->priv->need_im_reset = TRUE; |
---|
877 | return TRUE; |
---|
878 | } |
---|
879 | } |
---|
880 | |
---|
881 | if (html_class->use_emacs_bindings && html_class->emacs_bindings && !html->binding_handled) |
---|
882 | gtk_binding_set_activate (html_class->emacs_bindings, event->keyval, event->state, GTK_OBJECT (widget)); |
---|
883 | |
---|
884 | if (!html->binding_handled) |
---|
885 | GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); |
---|
886 | |
---|
887 | retval = html->binding_handled; |
---|
888 | update = html->priv->update_styles; |
---|
889 | |
---|
890 | if (retval && update) |
---|
891 | gtk_html_update_styles (html); |
---|
892 | |
---|
893 | html->priv->event_time = 0; |
---|
894 | |
---|
895 | /* FIXME: use bindings */ |
---|
896 | if (!html_engine_get_editable (html->engine)) { |
---|
897 | switch (event->keyval) { |
---|
898 | case GDK_Return: |
---|
899 | case GDK_KP_Enter: |
---|
900 | if (html->engine->focus_object) { |
---|
901 | gchar *url; |
---|
902 | url = html_object_get_complete_url (html->engine->focus_object, html->engine->focus_object_offset); |
---|
903 | if (url) { |
---|
904 | /* printf ("link clicked: %s\n", url); */ |
---|
905 | g_signal_emit (html, signals [LINK_CLICKED], 0, url); |
---|
906 | g_free (url); |
---|
907 | } |
---|
908 | } |
---|
909 | break; |
---|
910 | default: |
---|
911 | ; |
---|
912 | } |
---|
913 | } |
---|
914 | |
---|
915 | if (retval && (html_engine_get_editable (html->engine) || html->engine->caret_mode)) |
---|
916 | html_engine_reset_blinking_cursor (html->engine); |
---|
917 | |
---|
918 | /* printf ("retval: %d\n", retval); */ |
---|
919 | |
---|
920 | return retval; |
---|
921 | } |
---|
922 | |
---|
923 | static gint |
---|
924 | key_release_event (GtkWidget *widget, GdkEventKey *event) |
---|
925 | { |
---|
926 | GtkHTML *html = GTK_HTML (widget); |
---|
927 | |
---|
928 | if (!html->binding_handled && html_engine_get_editable (html->engine)) { |
---|
929 | if (gtk_im_context_filter_keypress (html->priv->im_context, event)) { |
---|
930 | html->priv->need_im_reset = TRUE; |
---|
931 | return TRUE; |
---|
932 | } |
---|
933 | } |
---|
934 | |
---|
935 | return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event); |
---|
936 | } |
---|
937 | |
---|
938 | void |
---|
939 | gtk_html_drag_dest_set (GtkHTML *html) |
---|
940 | { |
---|
941 | if (html_engine_get_editable (html->engine)) |
---|
942 | gtk_drag_dest_set (GTK_WIDGET (html), GTK_DEST_DEFAULT_ALL, |
---|
943 | dnd_link_sources, DND_LINK_SOURCES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); |
---|
944 | else |
---|
945 | gtk_drag_dest_unset (GTK_WIDGET (html)); |
---|
946 | } |
---|
947 | |
---|
948 | static void |
---|
949 | realize (GtkWidget *widget) |
---|
950 | { |
---|
951 | GtkHTML *html; |
---|
952 | GtkLayout *layout; |
---|
953 | |
---|
954 | g_return_if_fail (widget != NULL); |
---|
955 | g_return_if_fail (GTK_IS_HTML (widget)); |
---|
956 | |
---|
957 | html = GTK_HTML (widget); |
---|
958 | layout = GTK_LAYOUT (widget); |
---|
959 | |
---|
960 | if (GTK_WIDGET_CLASS (parent_class)->realize) |
---|
961 | (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); |
---|
962 | |
---|
963 | widget->style = gtk_style_attach (widget->style, widget->window); |
---|
964 | gdk_window_set_events (html->layout.bin_window, |
---|
965 | (gdk_window_get_events (html->layout.bin_window) |
---|
966 | | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK |
---|
967 | | GDK_ENTER_NOTIFY_MASK |
---|
968 | | GDK_BUTTON_PRESS_MASK |
---|
969 | | GDK_BUTTON_RELEASE_MASK |
---|
970 | | GDK_VISIBILITY_NOTIFY_MASK |
---|
971 | | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)); |
---|
972 | |
---|
973 | html_engine_realize (html->engine, html->layout.bin_window); |
---|
974 | |
---|
975 | gdk_window_set_cursor (widget->window, NULL); |
---|
976 | |
---|
977 | /* This sets the backing pixmap to None, so that scrolling does not |
---|
978 | erase the newly exposed area, thus making the thing smoother. */ |
---|
979 | gdk_window_set_back_pixmap (html->layout.bin_window, NULL, FALSE); |
---|
980 | |
---|
981 | /* If someone was silly enough to stick us in something that doesn't |
---|
982 | * have adjustments, go ahead and create them now since we expect them |
---|
983 | * and love them and pat them |
---|
984 | */ |
---|
985 | if (layout->hadjustment == NULL) { |
---|
986 | layout->hadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); |
---|
987 | |
---|
988 | g_object_ref (layout->hadjustment); |
---|
989 | gtk_object_sink (GTK_OBJECT (layout->hadjustment)); |
---|
990 | } |
---|
991 | |
---|
992 | if (layout->vadjustment == NULL) { |
---|
993 | layout->vadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); |
---|
994 | |
---|
995 | g_object_ref (layout->vadjustment); |
---|
996 | gtk_object_sink (GTK_OBJECT (layout->vadjustment)); |
---|
997 | } |
---|
998 | |
---|
999 | gtk_html_drag_dest_set (html); |
---|
1000 | |
---|
1001 | gtk_im_context_set_client_window (html->priv->im_context, widget->window); |
---|
1002 | |
---|
1003 | html_image_factory_start_animations (html->engine->image_factory); |
---|
1004 | } |
---|
1005 | |
---|
1006 | static void |
---|
1007 | unrealize (GtkWidget *widget) |
---|
1008 | { |
---|
1009 | GtkHTML *html = GTK_HTML (widget); |
---|
1010 | |
---|
1011 | html_engine_unrealize (html->engine); |
---|
1012 | |
---|
1013 | gtk_im_context_set_client_window (html->priv->im_context, widget->window); |
---|
1014 | |
---|
1015 | html_image_factory_stop_animations (html->engine->image_factory); |
---|
1016 | |
---|
1017 | if (GTK_WIDGET_CLASS (parent_class)->unrealize) |
---|
1018 | (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); |
---|
1019 | } |
---|
1020 | |
---|
1021 | static gboolean |
---|
1022 | expose (GtkWidget *widget, GdkEventExpose *event) |
---|
1023 | { |
---|
1024 | /* printf ("expose x: %d y: %d\n", GTK_HTML (widget)->engine->x_offset, GTK_HTML (widget)->engine->y_offset); */ |
---|
1025 | |
---|
1026 | html_engine_expose (GTK_HTML (widget)->engine, event); |
---|
1027 | |
---|
1028 | if (GTK_WIDGET_CLASS (parent_class)->expose_event) |
---|
1029 | (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); |
---|
1030 | /* printf ("expose END\n"); */ |
---|
1031 | |
---|
1032 | return FALSE; |
---|
1033 | } |
---|
1034 | |
---|
1035 | static void |
---|
1036 | gtk_html_size_request (GtkWidget *widget, GtkRequisition *requisition) |
---|
1037 | { |
---|
1038 | HTMLEngine *e = GTK_HTML (widget)->engine; |
---|
1039 | if (!e->writing) { |
---|
1040 | int old_width, old_height; |
---|
1041 | |
---|
1042 | old_width = e->width; |
---|
1043 | old_height = e->height; |
---|
1044 | e->width = requisition->width; |
---|
1045 | e->height = requisition->height; |
---|
1046 | html_engine_calc_size (e, NULL); |
---|
1047 | requisition->width = html_engine_get_doc_width (e); |
---|
1048 | requisition->height = html_engine_get_doc_height (e); |
---|
1049 | e->width = old_width; |
---|
1050 | e->height = old_height; |
---|
1051 | html_engine_calc_size (e, NULL); |
---|
1052 | } else { |
---|
1053 | requisition->width = html_engine_get_doc_width (e); |
---|
1054 | requisition->height = html_engine_get_doc_height (e); |
---|
1055 | } |
---|
1056 | } |
---|
1057 | |
---|
1058 | static void |
---|
1059 | child_size_allocate (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
1060 | { |
---|
1061 | if (html_object_is_embedded (o)) { |
---|
1062 | HTMLEmbedded *eo = HTML_EMBEDDED (o); |
---|
1063 | |
---|
1064 | if (eo->widget) { |
---|
1065 | GtkAllocation allocation; |
---|
1066 | |
---|
1067 | html_object_calc_abs_position (o, &allocation.x, &allocation.y); |
---|
1068 | allocation.y -= o->ascent; |
---|
1069 | allocation.width = o->width; |
---|
1070 | allocation.height = o->ascent + o->descent; |
---|
1071 | gtk_widget_size_allocate (eo->widget, &allocation); |
---|
1072 | } |
---|
1073 | } |
---|
1074 | } |
---|
1075 | |
---|
1076 | static void |
---|
1077 | size_allocate (GtkWidget *widget, GtkAllocation *allocation) |
---|
1078 | { |
---|
1079 | GtkHTML *html; |
---|
1080 | gboolean changed_x = FALSE, changed_y = FALSE; |
---|
1081 | GList *children; |
---|
1082 | |
---|
1083 | g_return_if_fail (widget != NULL); |
---|
1084 | g_return_if_fail (GTK_IS_HTML (widget)); |
---|
1085 | g_return_if_fail (allocation != NULL); |
---|
1086 | |
---|
1087 | /* isolate childs from layout - we want to set them after calc size is performed |
---|
1088 | and we know the children positions */ |
---|
1089 | children = GTK_LAYOUT (widget)->children; |
---|
1090 | GTK_LAYOUT (widget)->children = NULL; |
---|
1091 | if (GTK_WIDGET_CLASS (parent_class)->size_allocate) |
---|
1092 | (*GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation); |
---|
1093 | GTK_LAYOUT (widget)->children = children; |
---|
1094 | |
---|
1095 | html = GTK_HTML (widget); |
---|
1096 | |
---|
1097 | if (html->engine->width != allocation->width |
---|
1098 | || html->engine->height != allocation->height) { |
---|
1099 | HTMLEngine *e = html->engine; |
---|
1100 | gint old_doc_width, old_doc_height, old_width, old_height; |
---|
1101 | |
---|
1102 | old_doc_width = html_engine_get_doc_width (html->engine); |
---|
1103 | old_doc_height = html_engine_get_doc_height (html->engine); |
---|
1104 | old_width = e->width; |
---|
1105 | old_height = e->height; |
---|
1106 | |
---|
1107 | e->width = allocation->width; |
---|
1108 | e->height = allocation->height; |
---|
1109 | |
---|
1110 | html_engine_calc_size (html->engine, NULL); |
---|
1111 | gtk_html_update_scrollbars_on_resize (html, old_doc_width, old_doc_height, old_width, old_height, |
---|
1112 | &changed_x, &changed_y); |
---|
1113 | } |
---|
1114 | |
---|
1115 | if (!html->engine->keep_scroll) { |
---|
1116 | gtk_html_private_calc_scrollbars (html, &changed_x, &changed_y); |
---|
1117 | |
---|
1118 | if (changed_x) |
---|
1119 | gtk_adjustment_value_changed (GTK_LAYOUT (html)->hadjustment); |
---|
1120 | if (changed_y) |
---|
1121 | gtk_adjustment_value_changed (GTK_LAYOUT (html)->vadjustment); |
---|
1122 | } |
---|
1123 | |
---|
1124 | if (html->engine->clue) |
---|
1125 | html_object_forall (html->engine->clue, html->engine, child_size_allocate, NULL); |
---|
1126 | } |
---|
1127 | |
---|
1128 | static void |
---|
1129 | set_pointer_url (GtkHTML *html, const char *url) |
---|
1130 | { |
---|
1131 | if (url == html->pointer_url) |
---|
1132 | return; |
---|
1133 | |
---|
1134 | if (url && html->pointer_url && !strcmp (url, html->pointer_url)) |
---|
1135 | return; |
---|
1136 | |
---|
1137 | g_free (html->pointer_url); |
---|
1138 | html->pointer_url = url ? g_strdup (url) : NULL; |
---|
1139 | g_signal_emit (html, signals[ON_URL], 0, html->pointer_url); |
---|
1140 | } |
---|
1141 | |
---|
1142 | static void |
---|
1143 | dnd_link_set (GtkWidget *widget, HTMLObject *o, gint offset) |
---|
1144 | { |
---|
1145 | if (!html_engine_get_editable (GTK_HTML (widget)->engine)) { |
---|
1146 | /* printf ("dnd_link_set %p\n", o); */ |
---|
1147 | |
---|
1148 | gtk_drag_source_set (widget, GDK_BUTTON1_MASK, |
---|
1149 | dnd_link_sources, DND_LINK_SOURCES, |
---|
1150 | GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); |
---|
1151 | GTK_HTML (widget)->priv->dnd_object = o; |
---|
1152 | GTK_HTML (widget)->priv->dnd_object_offset = offset; |
---|
1153 | } |
---|
1154 | } |
---|
1155 | |
---|
1156 | static void |
---|
1157 | dnd_link_unset (GtkWidget *widget) |
---|
1158 | { |
---|
1159 | if (!html_engine_get_editable (GTK_HTML (widget)->engine)) { |
---|
1160 | /* printf ("dnd_link_unset\n"); */ |
---|
1161 | |
---|
1162 | gtk_drag_source_unset (widget); |
---|
1163 | GTK_HTML (widget)->priv->dnd_object = NULL; |
---|
1164 | } |
---|
1165 | } |
---|
1166 | |
---|
1167 | static void |
---|
1168 | on_object (GtkWidget *widget, GdkWindow *window, HTMLObject *obj, gint offset, gint x, gint y) |
---|
1169 | { |
---|
1170 | GtkHTML *html = GTK_HTML (widget); |
---|
1171 | |
---|
1172 | if (obj) { |
---|
1173 | gchar *url; |
---|
1174 | |
---|
1175 | if (gtk_html_get_editable (html)) { |
---|
1176 | if (HTML_IS_IMAGE (obj)) { |
---|
1177 | gint ox, oy; |
---|
1178 | |
---|
1179 | html_object_calc_abs_position (obj, &ox, &oy); |
---|
1180 | if (ox + obj->width - 5 <= x && oy + obj->descent - 5 <= y) { |
---|
1181 | gdk_window_set_cursor (window, html->priv->resize_cursor); |
---|
1182 | |
---|
1183 | return; |
---|
1184 | } |
---|
1185 | } |
---|
1186 | } |
---|
1187 | |
---|
1188 | url = gtk_html_get_url_object_relative (html, obj, |
---|
1189 | html_object_get_url (obj, offset)); |
---|
1190 | if (url != NULL) { |
---|
1191 | set_pointer_url (html, url); |
---|
1192 | dnd_link_set (widget, obj, offset); |
---|
1193 | |
---|
1194 | if (html->engine->editable) |
---|
1195 | gdk_window_set_cursor (window, html->ibeam_cursor); |
---|
1196 | else { |
---|
1197 | gdk_window_set_cursor (window, html->hand_cursor); |
---|
1198 | } |
---|
1199 | } else { |
---|
1200 | set_pointer_url (html, NULL); |
---|
1201 | dnd_link_unset (widget); |
---|
1202 | |
---|
1203 | if (html_object_is_text (obj) && html->allow_selection) |
---|
1204 | gdk_window_set_cursor (window, html->ibeam_cursor); |
---|
1205 | else |
---|
1206 | gdk_window_set_cursor (window, NULL); |
---|
1207 | } |
---|
1208 | |
---|
1209 | g_free (url); |
---|
1210 | } else { |
---|
1211 | set_pointer_url (html, NULL); |
---|
1212 | dnd_link_unset (widget); |
---|
1213 | |
---|
1214 | gdk_window_set_cursor (window, NULL); |
---|
1215 | } |
---|
1216 | } |
---|
1217 | |
---|
1218 | #define HTML_DIST(x,y) sqrt(x*x + y*y) |
---|
1219 | |
---|
1220 | static gint |
---|
1221 | mouse_change_pos (GtkWidget *widget, GdkWindow *window, gint x, gint y, gint state) |
---|
1222 | { |
---|
1223 | GtkHTML *html; |
---|
1224 | HTMLEngine *engine; |
---|
1225 | HTMLObject *obj; |
---|
1226 | HTMLType type; |
---|
1227 | gint offset; |
---|
1228 | |
---|
1229 | if (!GTK_WIDGET_REALIZED (widget)) |
---|
1230 | return FALSE; |
---|
1231 | |
---|
1232 | html = GTK_HTML (widget); |
---|
1233 | engine = html->engine; |
---|
1234 | obj = html_engine_get_object_at (engine, x, y, &offset, FALSE); |
---|
1235 | |
---|
1236 | if ((html->in_selection || html->in_selection_drag) && html->allow_selection) { |
---|
1237 | gboolean need_scroll; |
---|
1238 | |
---|
1239 | if (obj) { |
---|
1240 | type = HTML_OBJECT_TYPE (obj); |
---|
1241 | |
---|
1242 | /* FIXME this is broken */ |
---|
1243 | |
---|
1244 | if (type == HTML_TYPE_BUTTON || |
---|
1245 | type == HTML_TYPE_CHECKBOX || |
---|
1246 | type == HTML_TYPE_EMBEDDED || |
---|
1247 | type == HTML_TYPE_HIDDEN || |
---|
1248 | type == HTML_TYPE_IMAGEINPUT || |
---|
1249 | type == HTML_TYPE_RADIO || |
---|
1250 | type == HTML_TYPE_SELECT || |
---|
1251 | type == HTML_TYPE_TEXTAREA || |
---|
1252 | type == HTML_TYPE_TEXTINPUT ) { |
---|
1253 | return FALSE; |
---|
1254 | } |
---|
1255 | } |
---|
1256 | |
---|
1257 | if (HTML_DIST ((x - html->selection_x1), (y - html->selection_y1)) |
---|
1258 | > html_painter_get_space_width (engine->painter, GTK_HTML_FONT_STYLE_SIZE_3, NULL)) { |
---|
1259 | html->in_selection = TRUE; |
---|
1260 | html->in_selection_drag = TRUE; |
---|
1261 | } |
---|
1262 | |
---|
1263 | need_scroll = FALSE; |
---|
1264 | |
---|
1265 | if (x < html->engine->x_offset) { |
---|
1266 | need_scroll = TRUE; |
---|
1267 | } else if (x >= widget->allocation.width) { |
---|
1268 | need_scroll = TRUE; |
---|
1269 | } |
---|
1270 | |
---|
1271 | if (y < html->engine->y_offset) { |
---|
1272 | need_scroll = TRUE; |
---|
1273 | } else if (y >= widget->allocation.height) { |
---|
1274 | need_scroll = TRUE; |
---|
1275 | } |
---|
1276 | |
---|
1277 | if (need_scroll) |
---|
1278 | setup_scroll_timeout (html); |
---|
1279 | else |
---|
1280 | remove_scroll_timeout (html); |
---|
1281 | |
---|
1282 | /* This will put the mark at the position of the |
---|
1283 | previous click. */ |
---|
1284 | if (engine->mark == NULL && engine->editable) |
---|
1285 | html_engine_set_mark (engine); |
---|
1286 | |
---|
1287 | html_engine_select_region (engine, html->selection_x1, html->selection_y1, x, y); |
---|
1288 | } |
---|
1289 | |
---|
1290 | if (html->priv->in_object_resize) { |
---|
1291 | HTMLObject *o = html->priv->resize_object; |
---|
1292 | gint ox, oy; |
---|
1293 | |
---|
1294 | html_object_calc_abs_position (o, &ox, &oy); |
---|
1295 | oy -= o->ascent; |
---|
1296 | g_assert (HTML_IS_IMAGE (o)); |
---|
1297 | if (x > ox && y > oy) { |
---|
1298 | gint w, h; |
---|
1299 | |
---|
1300 | w = x - ox; |
---|
1301 | h = y - oy; |
---|
1302 | if (!(state & GDK_SHIFT_MASK)) { |
---|
1303 | w = MAX (w, h); |
---|
1304 | h = -1; |
---|
1305 | } |
---|
1306 | html_image_set_size (HTML_IMAGE (o), w, h, FALSE, FALSE); |
---|
1307 | } |
---|
1308 | } else |
---|
1309 | on_object (widget, window, obj, offset, x, y); |
---|
1310 | |
---|
1311 | return TRUE; |
---|
1312 | } |
---|
1313 | |
---|
1314 | static const char * |
---|
1315 | skip_host (const char *url) |
---|
1316 | { |
---|
1317 | const char *host; |
---|
1318 | |
---|
1319 | host = url; |
---|
1320 | while (*host && (*host != '/') && (*host != ':')) |
---|
1321 | host++; |
---|
1322 | |
---|
1323 | if (*host == ':') { |
---|
1324 | url = host++; |
---|
1325 | |
---|
1326 | if (*host == '/') |
---|
1327 | host++; |
---|
1328 | |
---|
1329 | url = host; |
---|
1330 | |
---|
1331 | if (*host == '/') { |
---|
1332 | host++; |
---|
1333 | |
---|
1334 | while (*host && (*host != '/')) |
---|
1335 | host++; |
---|
1336 | |
---|
1337 | url = host; |
---|
1338 | } |
---|
1339 | } |
---|
1340 | |
---|
1341 | return url; |
---|
1342 | } |
---|
1343 | |
---|
1344 | static size_t |
---|
1345 | path_len (const char *base, gboolean absolute) |
---|
1346 | { |
---|
1347 | const char *last; |
---|
1348 | const char *cur; |
---|
1349 | const char *start; |
---|
1350 | |
---|
1351 | start = last = skip_host (base); |
---|
1352 | if (!absolute) { |
---|
1353 | cur = strrchr (start, '/'); |
---|
1354 | |
---|
1355 | if (cur) |
---|
1356 | last = cur; |
---|
1357 | } |
---|
1358 | |
---|
1359 | return last - base; |
---|
1360 | } |
---|
1361 | |
---|
1362 | #if 0 |
---|
1363 | char * |
---|
1364 | collapse_path (char *url) |
---|
1365 | { |
---|
1366 | char *start; |
---|
1367 | char *end; |
---|
1368 | char *cur; |
---|
1369 | size_t len; |
---|
1370 | |
---|
1371 | start = skip_host (url); |
---|
1372 | |
---|
1373 | cur = start; |
---|
1374 | while ((cur = strstr (cur, "/../"))) { |
---|
1375 | end = cur + 3; |
---|
1376 | |
---|
1377 | /* handle the case of a rootlevel /../ specialy */ |
---|
1378 | if (cur == start) { |
---|
1379 | len = strlen (end); |
---|
1380 | memmove (cur, end, len + 1); |
---|
1381 | } |
---|
1382 | |
---|
1383 | while (cur > start) { |
---|
1384 | cur--; |
---|
1385 | if ((*cur == '/') || (cur == start)) { |
---|
1386 | len = strlen (end); |
---|
1387 | memmove (cur, end, len + 1); |
---|
1388 | break; |
---|
1389 | } |
---|
1390 | } |
---|
1391 | } |
---|
1392 | return url; |
---|
1393 | } |
---|
1394 | #endif |
---|
1395 | |
---|
1396 | static gboolean |
---|
1397 | url_is_absolute (const char *url) |
---|
1398 | { |
---|
1399 | /* |
---|
1400 | URI Syntactic Components |
---|
1401 | |
---|
1402 | The URI syntax is dependent upon the scheme. In general, absolute |
---|
1403 | URI are written as follows: |
---|
1404 | |
---|
1405 | <scheme>:<scheme-specific-part> |
---|
1406 | |
---|
1407 | scheme = alpha *( alpha | digit | "+" | "-" | "." ) |
---|
1408 | */ |
---|
1409 | |
---|
1410 | if (!url) |
---|
1411 | return FALSE; |
---|
1412 | |
---|
1413 | if (!isalpha (*url)) |
---|
1414 | return FALSE; |
---|
1415 | url ++; |
---|
1416 | |
---|
1417 | while (*url && (isalnum (*url) || *url == '+' || *url == '-' || *url == '.')) |
---|
1418 | url ++; |
---|
1419 | |
---|
1420 | return *url && *url == ':'; |
---|
1421 | } |
---|
1422 | |
---|
1423 | static char * |
---|
1424 | expand_relative (const char *base, const char *url) |
---|
1425 | { |
---|
1426 | char *new_url = NULL; |
---|
1427 | size_t base_len, url_len; |
---|
1428 | gboolean absolute = FALSE; |
---|
1429 | |
---|
1430 | if (!base || url_is_absolute (url)) { |
---|
1431 | /* |
---|
1432 | g_warning ("base = %s url = %s new_url = %s", |
---|
1433 | base, url, new_url); |
---|
1434 | */ |
---|
1435 | return g_strdup (url); |
---|
1436 | } |
---|
1437 | |
---|
1438 | if (*url == '/') { |
---|
1439 | absolute = TRUE;; |
---|
1440 | } |
---|
1441 | |
---|
1442 | base_len = path_len (base, absolute); |
---|
1443 | url_len = strlen (url); |
---|
1444 | |
---|
1445 | new_url = g_malloc (base_len + url_len + 2); |
---|
1446 | |
---|
1447 | if (base_len) { |
---|
1448 | memcpy (new_url, base, base_len); |
---|
1449 | |
---|
1450 | if (base[base_len - 1] != '/') |
---|
1451 | new_url[base_len++] = '/'; |
---|
1452 | if (absolute) |
---|
1453 | url++; |
---|
1454 | } |
---|
1455 | |
---|
1456 | memcpy (new_url + base_len, url, url_len); |
---|
1457 | new_url[base_len + url_len] = '\0'; |
---|
1458 | |
---|
1459 | /* |
---|
1460 | g_warning ("base = %s url = %s new_url = %s", |
---|
1461 | base, url, new_url); |
---|
1462 | */ |
---|
1463 | return new_url; |
---|
1464 | } |
---|
1465 | |
---|
1466 | char * |
---|
1467 | gtk_html_get_url_base_relative (GtkHTML *html, const char *url) |
---|
1468 | { |
---|
1469 | return expand_relative (gtk_html_get_base (html), url); |
---|
1470 | } |
---|
1471 | |
---|
1472 | static char * |
---|
1473 | expand_frame_url (GtkHTML *html, const char *url) |
---|
1474 | { |
---|
1475 | char *new_url; |
---|
1476 | |
---|
1477 | new_url = gtk_html_get_url_base_relative (html, url); |
---|
1478 | while (html->iframe_parent) { |
---|
1479 | char *expanded; |
---|
1480 | |
---|
1481 | expanded = gtk_html_get_url_base_relative (GTK_HTML (html->iframe_parent), |
---|
1482 | new_url); |
---|
1483 | g_free (new_url); |
---|
1484 | new_url = expanded; |
---|
1485 | |
---|
1486 | html = GTK_HTML (html->iframe_parent); |
---|
1487 | } |
---|
1488 | return new_url; |
---|
1489 | } |
---|
1490 | |
---|
1491 | char * |
---|
1492 | gtk_html_get_url_object_relative (GtkHTML *html, HTMLObject *o, const char *url) |
---|
1493 | { |
---|
1494 | HTMLEngine *e; |
---|
1495 | HTMLObject *parent; |
---|
1496 | |
---|
1497 | g_return_val_if_fail (GTK_IS_HTML (html), NULL); |
---|
1498 | |
---|
1499 | /* start at the top always */ |
---|
1500 | while (html->iframe_parent) |
---|
1501 | html = GTK_HTML (html->iframe_parent); |
---|
1502 | |
---|
1503 | parent = o; |
---|
1504 | while (parent->parent) { |
---|
1505 | parent = parent->parent; |
---|
1506 | if ((HTML_OBJECT_TYPE (parent) == HTML_TYPE_FRAME) |
---|
1507 | || (HTML_OBJECT_TYPE (parent) == HTML_TYPE_IFRAME)) |
---|
1508 | break; |
---|
1509 | } |
---|
1510 | |
---|
1511 | e = html_object_get_engine (parent, html->engine); |
---|
1512 | |
---|
1513 | if (!e) { |
---|
1514 | g_warning ("Cannot find object for url"); |
---|
1515 | return NULL; |
---|
1516 | } |
---|
1517 | |
---|
1518 | /* |
---|
1519 | if (e == html->engine) |
---|
1520 | g_warning ("engine matches engine"); |
---|
1521 | */ |
---|
1522 | return url ? expand_frame_url (e->widget, url) : NULL; |
---|
1523 | } |
---|
1524 | |
---|
1525 | static GtkWidget * |
---|
1526 | shift_to_iframe_parent (GtkWidget *widget, gint *x, gint *y) |
---|
1527 | { |
---|
1528 | while (GTK_HTML (widget)->iframe_parent) { |
---|
1529 | if (x) |
---|
1530 | *x += widget->allocation.x - GTK_HTML (widget)->engine->x_offset; |
---|
1531 | if (y) |
---|
1532 | *y += widget->allocation.y - GTK_HTML (widget)->engine->y_offset; |
---|
1533 | |
---|
1534 | widget = GTK_HTML (widget)->iframe_parent; |
---|
1535 | |
---|
1536 | |
---|
1537 | } |
---|
1538 | |
---|
1539 | return widget; |
---|
1540 | } |
---|
1541 | |
---|
1542 | static gint |
---|
1543 | motion_notify_event (GtkWidget *widget, |
---|
1544 | GdkEventMotion *event) |
---|
1545 | { |
---|
1546 | GdkWindow *window = widget->window; |
---|
1547 | HTMLEngine *engine; |
---|
1548 | gint x, y; |
---|
1549 | |
---|
1550 | g_return_val_if_fail (widget != NULL, 0); |
---|
1551 | g_return_val_if_fail (GTK_IS_HTML (widget), 0); |
---|
1552 | g_return_val_if_fail (event != NULL, 0); |
---|
1553 | |
---|
1554 | /* printf ("motion_notify_event\n"); */ |
---|
1555 | |
---|
1556 | if (GTK_HTML (widget)->priv->dnd_in_progress) |
---|
1557 | return TRUE; |
---|
1558 | |
---|
1559 | if (!event->is_hint) { |
---|
1560 | x = event->x; |
---|
1561 | y = event->y; |
---|
1562 | } |
---|
1563 | widget = shift_to_iframe_parent (widget, &x, &y); |
---|
1564 | |
---|
1565 | if (event->is_hint) { |
---|
1566 | gdk_window_get_pointer (GTK_LAYOUT (widget)->bin_window, &x, &y, NULL); |
---|
1567 | } |
---|
1568 | |
---|
1569 | if (!mouse_change_pos (widget, window, x, y, event->state)) |
---|
1570 | return FALSE; |
---|
1571 | |
---|
1572 | engine = GTK_HTML (widget)->engine; |
---|
1573 | if (GTK_HTML (widget)->in_selection_drag && html_engine_get_editable (engine)) |
---|
1574 | html_engine_jump_at (engine, x, y); |
---|
1575 | return TRUE; |
---|
1576 | } |
---|
1577 | |
---|
1578 | |
---|
1579 | static gboolean |
---|
1580 | toplevel_unmap (GtkWidget *widget, GdkEvent *event, GtkHTML *html) |
---|
1581 | { |
---|
1582 | html_image_factory_stop_animations (html->engine->image_factory); |
---|
1583 | |
---|
1584 | return FALSE; |
---|
1585 | } |
---|
1586 | |
---|
1587 | static void |
---|
1588 | hierarchy_changed (GtkWidget *widget, |
---|
1589 | GtkWidget *old_toplevel) |
---|
1590 | { |
---|
1591 | GtkWidget *toplevel; |
---|
1592 | GtkHTMLPrivate *priv = GTK_HTML (widget)->priv; |
---|
1593 | |
---|
1594 | if (old_toplevel && priv->toplevel_unmap_handler) { |
---|
1595 | g_signal_handler_disconnect (old_toplevel, |
---|
1596 | priv->toplevel_unmap_handler); |
---|
1597 | priv->toplevel_unmap_handler = 0; |
---|
1598 | } |
---|
1599 | |
---|
1600 | toplevel = gtk_widget_get_toplevel (widget); |
---|
1601 | |
---|
1602 | if (GTK_WIDGET_TOPLEVEL (toplevel) && priv->toplevel_unmap_handler == 0) { |
---|
1603 | priv->toplevel_unmap_handler = g_signal_connect (G_OBJECT (toplevel), "unmap-event", |
---|
1604 | G_CALLBACK (toplevel_unmap), widget); |
---|
1605 | } |
---|
1606 | } |
---|
1607 | |
---|
1608 | static gint |
---|
1609 | visibility_notify_event (GtkWidget *widget, |
---|
1610 | GdkEventVisibility *event) |
---|
1611 | { |
---|
1612 | if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) |
---|
1613 | html_image_factory_stop_animations (GTK_HTML (widget)->engine->image_factory); |
---|
1614 | else |
---|
1615 | html_image_factory_start_animations (GTK_HTML (widget)->engine->image_factory); |
---|
1616 | |
---|
1617 | return FALSE; |
---|
1618 | } |
---|
1619 | |
---|
1620 | static gint |
---|
1621 | button_press_event (GtkWidget *widget, |
---|
1622 | GdkEventButton *event) |
---|
1623 | { |
---|
1624 | GtkHTML *html; |
---|
1625 | GtkWidget *orig_widget = widget; |
---|
1626 | HTMLEngine *engine; |
---|
1627 | gint value, x, y; |
---|
1628 | |
---|
1629 | /* printf ("button_press_event\n"); */ |
---|
1630 | |
---|
1631 | x = event->x; |
---|
1632 | y = event->y; |
---|
1633 | |
---|
1634 | widget = shift_to_iframe_parent (widget, &x, &y); |
---|
1635 | html = GTK_HTML (widget); |
---|
1636 | engine = html->engine; |
---|
1637 | |
---|
1638 | if (event->button == 1 || ((event->button == 2 || event->button == 3) |
---|
1639 | && html_engine_get_editable (engine))) |
---|
1640 | gtk_widget_grab_focus (widget); |
---|
1641 | |
---|
1642 | if (event->type == GDK_BUTTON_PRESS) { |
---|
1643 | GtkAdjustment *vadj; |
---|
1644 | |
---|
1645 | vadj = GTK_LAYOUT (widget)->vadjustment; |
---|
1646 | |
---|
1647 | switch (event->button) { |
---|
1648 | case 4: |
---|
1649 | /* Mouse wheel scroll up. */ |
---|
1650 | if (event->state & GDK_CONTROL_MASK) |
---|
1651 | gtk_html_command (html, "zoom-out"); |
---|
1652 | else { |
---|
1653 | value = vadj->value - vadj->step_increment * 3; |
---|
1654 | |
---|
1655 | if (value < vadj->lower) |
---|
1656 | value = vadj->lower; |
---|
1657 | |
---|
1658 | gtk_adjustment_set_value (vadj, value); |
---|
1659 | } |
---|
1660 | return TRUE; |
---|
1661 | break; |
---|
1662 | case 5: |
---|
1663 | /* Mouse wheel scroll down. */ |
---|
1664 | if (event->state & GDK_CONTROL_MASK) |
---|
1665 | gtk_html_command (html, "zoom-in"); |
---|
1666 | else { |
---|
1667 | value = vadj->value + vadj->step_increment * 3; |
---|
1668 | |
---|
1669 | if (value > (vadj->upper - vadj->page_size)) |
---|
1670 | value = vadj->upper - vadj->page_size; |
---|
1671 | |
---|
1672 | gtk_adjustment_set_value (vadj, value); |
---|
1673 | } |
---|
1674 | return TRUE; |
---|
1675 | break; |
---|
1676 | case 2: |
---|
1677 | if (html_engine_get_editable (engine)) { |
---|
1678 | html_engine_disable_selection (html->engine); |
---|
1679 | html_engine_jump_at (engine, x, y); |
---|
1680 | gtk_html_update_styles (html); |
---|
1681 | gtk_html_request_paste (html, GDK_SELECTION_PRIMARY, |
---|
1682 | event->state & GDK_CONTROL_MASK ? 1 : 0, |
---|
1683 | event->time, event->state & GDK_SHIFT_MASK); |
---|
1684 | return TRUE; |
---|
1685 | } |
---|
1686 | break; |
---|
1687 | case 1: |
---|
1688 | html->in_selection_drag = TRUE; |
---|
1689 | if (html_engine_get_editable (engine)) { |
---|
1690 | HTMLObject *obj; |
---|
1691 | |
---|
1692 | obj = html_engine_get_object_at (engine, x, y, NULL, FALSE); |
---|
1693 | |
---|
1694 | if (obj && HTML_IS_IMAGE (obj)) { |
---|
1695 | gint ox, oy; |
---|
1696 | |
---|
1697 | html_object_calc_abs_position (obj, &ox, &oy); |
---|
1698 | if (ox + obj->width - 5 <= x && oy + obj->descent - 5 <= y) { |
---|
1699 | html->priv->in_object_resize = TRUE; |
---|
1700 | html->priv->resize_object = obj; |
---|
1701 | html->in_selection_drag = FALSE; |
---|
1702 | } |
---|
1703 | } |
---|
1704 | |
---|
1705 | if (html->allow_selection && !html->priv->in_object_resize) |
---|
1706 | if (!(event->state & GDK_SHIFT_MASK) |
---|
1707 | || (!engine->mark && event->state & GDK_SHIFT_MASK)) |
---|
1708 | html_engine_set_mark (engine); |
---|
1709 | html_engine_jump_at (engine, x, y); |
---|
1710 | } else { |
---|
1711 | HTMLObject *obj; |
---|
1712 | HTMLEngine *orig_e; |
---|
1713 | gint offset; |
---|
1714 | |
---|
1715 | orig_e = GTK_HTML (orig_widget)->engine; |
---|
1716 | obj = html_engine_get_object_at (engine, x, y, &offset, FALSE); |
---|
1717 | if (obj && ((HTML_IS_IMAGE (obj) && HTML_IMAGE (obj)->url && *HTML_IMAGE (obj)->url) |
---|
1718 | || (HTML_IS_TEXT (obj) && html_object_get_complete_url (obj, offset)))) |
---|
1719 | html_engine_set_focus_object (orig_e, obj, offset); |
---|
1720 | else { |
---|
1721 | html_engine_set_focus_object (orig_e, NULL, 0); |
---|
1722 | if (orig_e->caret_mode) |
---|
1723 | html_engine_jump_at (engine, x, y); |
---|
1724 | } |
---|
1725 | } |
---|
1726 | if (html->allow_selection && !html->priv->in_object_resize) { |
---|
1727 | if (event->state & GDK_SHIFT_MASK) |
---|
1728 | html_engine_select_region (engine, |
---|
1729 | html->selection_x1, html->selection_y1, x, y); |
---|
1730 | else { |
---|
1731 | html_engine_disable_selection (engine); |
---|
1732 | if (gdk_pointer_grab (GTK_LAYOUT (widget)->bin_window, FALSE, |
---|
1733 | (GDK_BUTTON_RELEASE_MASK |
---|
1734 | | GDK_BUTTON_MOTION_MASK |
---|
1735 | | GDK_POINTER_MOTION_HINT_MASK), |
---|
1736 | NULL, NULL, event->time) == 0) { |
---|
1737 | html->selection_x1 = x; |
---|
1738 | html->selection_y1 = y; |
---|
1739 | } |
---|
1740 | } |
---|
1741 | } |
---|
1742 | |
---|
1743 | engine->selection_mode = FALSE; |
---|
1744 | if (html_engine_get_editable (engine)) |
---|
1745 | gtk_html_update_styles (html); |
---|
1746 | break; |
---|
1747 | default: |
---|
1748 | break; |
---|
1749 | } |
---|
1750 | } else if (event->button == 1 && html->allow_selection) { |
---|
1751 | if (event->type == GDK_2BUTTON_PRESS) { |
---|
1752 | html->in_selection_drag = FALSE; |
---|
1753 | gtk_html_select_word (html); |
---|
1754 | html->in_selection = TRUE; |
---|
1755 | } |
---|
1756 | else if (event->type == GDK_3BUTTON_PRESS) { |
---|
1757 | html->in_selection_drag = FALSE; |
---|
1758 | gtk_html_select_line (html); |
---|
1759 | html->in_selection = TRUE; |
---|
1760 | } |
---|
1761 | } |
---|
1762 | |
---|
1763 | return FALSE; |
---|
1764 | } |
---|
1765 | |
---|
1766 | static gint |
---|
1767 | button_release_event (GtkWidget *initial_widget, |
---|
1768 | GdkEventButton *event) |
---|
1769 | { |
---|
1770 | GtkWidget *widget; |
---|
1771 | GtkHTML *html; |
---|
1772 | HTMLEngine *engine; |
---|
1773 | gint x, y; |
---|
1774 | |
---|
1775 | /* printf ("button_release_event\n"); */ |
---|
1776 | |
---|
1777 | x = event->x; |
---|
1778 | y = event->y; |
---|
1779 | widget = shift_to_iframe_parent (initial_widget, &x, &y); |
---|
1780 | html = GTK_HTML (widget); |
---|
1781 | |
---|
1782 | remove_scroll_timeout (html); |
---|
1783 | gtk_grab_remove (widget); |
---|
1784 | gdk_pointer_ungrab (event->time); |
---|
1785 | |
---|
1786 | engine = html->engine; |
---|
1787 | |
---|
1788 | if (html->in_selection) { |
---|
1789 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
1790 | if (html->in_selection_drag) |
---|
1791 | html_engine_select_region (engine, html->selection_x1, html->selection_y1, |
---|
1792 | x, y); |
---|
1793 | gtk_html_update_styles (html); |
---|
1794 | queue_draw (html); |
---|
1795 | } |
---|
1796 | |
---|
1797 | if (event->button == 1) { |
---|
1798 | |
---|
1799 | if (html->in_selection_drag && html_engine_get_editable (engine)) |
---|
1800 | html_engine_jump_at (engine, x, y); |
---|
1801 | |
---|
1802 | html->in_selection_drag = FALSE; |
---|
1803 | |
---|
1804 | if (!html->priv->dnd_in_progress |
---|
1805 | && html->pointer_url != NULL && ! html->in_selection) |
---|
1806 | g_signal_emit (widget, signals[LINK_CLICKED], 0, html->pointer_url); |
---|
1807 | } |
---|
1808 | |
---|
1809 | html->in_selection = FALSE; |
---|
1810 | html->priv->in_object_resize = FALSE; |
---|
1811 | |
---|
1812 | return TRUE; |
---|
1813 | } |
---|
1814 | |
---|
1815 | static gint |
---|
1816 | focus_in_event (GtkWidget *widget, |
---|
1817 | GdkEventFocus *event) |
---|
1818 | { |
---|
1819 | GtkHTML *html = GTK_HTML (widget); |
---|
1820 | |
---|
1821 | /* printf ("focus in\n"); */ |
---|
1822 | if (!html->iframe_parent) { |
---|
1823 | GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); |
---|
1824 | html_engine_set_focus (html->engine, TRUE); |
---|
1825 | } else { |
---|
1826 | GtkWidget *window = gtk_widget_get_ancestor (widget, gtk_window_get_type ()); |
---|
1827 | if (window) |
---|
1828 | gtk_window_set_focus (GTK_WINDOW (window), html->iframe_parent); |
---|
1829 | } |
---|
1830 | |
---|
1831 | html->priv->need_im_reset = TRUE; |
---|
1832 | gtk_im_context_focus_in (html->priv->im_context); |
---|
1833 | |
---|
1834 | return FALSE; |
---|
1835 | } |
---|
1836 | |
---|
1837 | static gint |
---|
1838 | focus_out_event (GtkWidget *widget, |
---|
1839 | GdkEventFocus *event) |
---|
1840 | { |
---|
1841 | GtkHTML *html = GTK_HTML (widget); |
---|
1842 | |
---|
1843 | html_painter_set_focus (html->engine->painter, FALSE); |
---|
1844 | html_engine_redraw_selection (html->engine); |
---|
1845 | /* printf ("focus out\n"); */ |
---|
1846 | if (!html->iframe_parent) { |
---|
1847 | GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); |
---|
1848 | html_engine_set_focus (html->engine, FALSE); |
---|
1849 | } |
---|
1850 | |
---|
1851 | html->priv->need_im_reset = TRUE; |
---|
1852 | gtk_im_context_focus_out (html->priv->im_context); |
---|
1853 | |
---|
1854 | return FALSE; |
---|
1855 | } |
---|
1856 | |
---|
1857 | static gint |
---|
1858 | enter_notify_event (GtkWidget *widget, GdkEventCrossing *event) |
---|
1859 | { |
---|
1860 | gint x, y; |
---|
1861 | |
---|
1862 | x = event->x; |
---|
1863 | y = event->y; |
---|
1864 | widget = shift_to_iframe_parent (widget, &x, &y); |
---|
1865 | |
---|
1866 | mouse_change_pos (widget, widget->window, x, y, event->state); |
---|
1867 | |
---|
1868 | return TRUE; |
---|
1869 | } |
---|
1870 | |
---|
1871 | /* X11 selection support. */ |
---|
1872 | |
---|
1873 | static char * |
---|
1874 | ucs2_order (gboolean swap) |
---|
1875 | { |
---|
1876 | gboolean be; |
---|
1877 | |
---|
1878 | /* |
---|
1879 | * FIXME owen tells me this logic probably isn't needed |
---|
1880 | * because smart iconvs will notice the BOM and act accordingly |
---|
1881 | * I don't have as much faith in the various iconv implementations |
---|
1882 | * so I am leaving it in for now |
---|
1883 | */ |
---|
1884 | |
---|
1885 | be = G_BYTE_ORDER == G_BIG_ENDIAN; |
---|
1886 | be = swap ? be : !be; |
---|
1887 | |
---|
1888 | if (be) |
---|
1889 | return "UCS-2BE"; |
---|
1890 | else |
---|
1891 | return "UCS-2LE"; |
---|
1892 | |
---|
1893 | } |
---|
1894 | |
---|
1895 | static void |
---|
1896 | selection_get (GtkWidget *widget, |
---|
1897 | GtkSelectionData *selection_data, |
---|
1898 | guint info, |
---|
1899 | guint time) |
---|
1900 | { |
---|
1901 | GtkHTML *html; |
---|
1902 | gchar *selection_string = NULL; |
---|
1903 | HTMLObject *selection_object = NULL; |
---|
1904 | guint selection_object_len = 0; |
---|
1905 | |
---|
1906 | g_return_if_fail (widget != NULL); |
---|
1907 | g_return_if_fail (GTK_IS_HTML (widget)); |
---|
1908 | |
---|
1909 | html = GTK_HTML (widget); |
---|
1910 | if (selection_data->selection == GDK_SELECTION_PRIMARY) { |
---|
1911 | if (html->engine->primary) { |
---|
1912 | selection_object = html->engine->primary; |
---|
1913 | selection_object_len = html->engine->primary_len; |
---|
1914 | } |
---|
1915 | } else /* CLIPBOARD */ { |
---|
1916 | if (html->engine->clipboard) { |
---|
1917 | selection_object = html->engine->clipboard; |
---|
1918 | selection_object_len = html->engine->clipboard_len; |
---|
1919 | } |
---|
1920 | } |
---|
1921 | |
---|
1922 | if (info == TARGET_HTML) { |
---|
1923 | if (selection_object) { |
---|
1924 | HTMLEngineSaveState *state; |
---|
1925 | GString *buffer; |
---|
1926 | gsize len; |
---|
1927 | |
---|
1928 | state = html_engine_save_buffer_new (html->engine, TRUE); |
---|
1929 | buffer = (GString *)state->user_data; |
---|
1930 | |
---|
1931 | /* prepend a byte order marker (ZWNBSP) to the selection */ |
---|
1932 | g_string_append_unichar (buffer, 0xfeff); |
---|
1933 | html_object_save (selection_object, state); |
---|
1934 | g_string_append_unichar (buffer, 0x0000); |
---|
1935 | |
---|
1936 | d_s(g_warning ("BUFFER = %s", buffer->str);) |
---|
1937 | selection_string = g_convert (buffer->str, buffer->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
---|
1938 | |
---|
1939 | if (selection_string) |
---|
1940 | gtk_selection_data_set (selection_data, |
---|
1941 | gdk_atom_intern ("text/html", FALSE), 8, |
---|
1942 | selection_string, |
---|
1943 | len); |
---|
1944 | |
---|
1945 | //html_engine_save_buffer_free (state); |
---|
1946 | } |
---|
1947 | } else { |
---|
1948 | if (selection_object) |
---|
1949 | selection_string = html_object_get_selection_string (selection_object, html->engine); |
---|
1950 | |
---|
1951 | if (selection_string) |
---|
1952 | gtk_selection_data_set_text (selection_data, selection_string, strlen (selection_string)); |
---|
1953 | |
---|
1954 | } |
---|
1955 | |
---|
1956 | g_free (selection_string); |
---|
1957 | |
---|
1958 | } |
---|
1959 | |
---|
1960 | static gchar * |
---|
1961 | ucs2_to_utf8_with_bom_check (guchar *data, guint len) { |
---|
1962 | char *fromcode = NULL; |
---|
1963 | GError *error = NULL; |
---|
1964 | guint16 c; |
---|
1965 | gsize read_len, written_len; |
---|
1966 | gchar *utf8_ret; |
---|
1967 | |
---|
1968 | /* |
---|
1969 | * Unicode Techinical Report 20 |
---|
1970 | * ( http://www.unicode.org/unicode/reports/tr20/ ) says to treat an |
---|
1971 | * initial 0xfeff (ZWNBSP) as a byte order indicator so that is |
---|
1972 | * what we do. If there is no indicator assume it is in the default |
---|
1973 | * order |
---|
1974 | */ |
---|
1975 | |
---|
1976 | memcpy (&c, data, 2); |
---|
1977 | switch (c) { |
---|
1978 | case 0xfeff: |
---|
1979 | case 0xfffe: |
---|
1980 | fromcode = ucs2_order (c == 0xfeff); |
---|
1981 | data += 2; |
---|
1982 | len -= 2; |
---|
1983 | break; |
---|
1984 | default: |
---|
1985 | fromcode = "UCS-2"; |
---|
1986 | break; |
---|
1987 | } |
---|
1988 | |
---|
1989 | utf8_ret = g_convert (data, len, "UTF-8", fromcode, &read_len, &written_len, &error); |
---|
1990 | |
---|
1991 | if (error) { |
---|
1992 | g_warning ("g_convert error: %s\n", error->message); |
---|
1993 | g_error_free (error); |
---|
1994 | } |
---|
1995 | return (utf8_ret); |
---|
1996 | } |
---|
1997 | |
---|
1998 | /* receive a selection */ |
---|
1999 | /* Signal handler called when the selections owner returns the data */ |
---|
2000 | static void |
---|
2001 | selection_received (GtkWidget *widget, |
---|
2002 | GtkSelectionData *selection_data, |
---|
2003 | guint time) |
---|
2004 | { |
---|
2005 | HTMLEngine *e; |
---|
2006 | gboolean as_cite; |
---|
2007 | |
---|
2008 | g_return_if_fail (widget != NULL); |
---|
2009 | g_return_if_fail (GTK_IS_HTML (widget)); |
---|
2010 | g_return_if_fail (selection_data != NULL); |
---|
2011 | |
---|
2012 | /* printf ("got selection from system\n"); */ |
---|
2013 | |
---|
2014 | e = GTK_HTML (widget)->engine; |
---|
2015 | as_cite = GTK_HTML (widget)->priv->selection_as_cite; |
---|
2016 | |
---|
2017 | /* If the Widget is editable, |
---|
2018 | ** and we are the owner of the atom requested |
---|
2019 | ** and we are not pasting as a citation |
---|
2020 | ** then we are pasting between ourself and we |
---|
2021 | ** need not do all the conversion. |
---|
2022 | */ |
---|
2023 | if (html_engine_get_editable (e) |
---|
2024 | && widget->window == gdk_selection_owner_get (selection_data->selection) |
---|
2025 | && !as_cite) { |
---|
2026 | |
---|
2027 | /* Check which atom was requested (PRIMARY or CLIPBOARD) */ |
---|
2028 | if (selection_data->selection == gdk_atom_intern ("CLIPBOARD", FALSE) |
---|
2029 | && e->clipboard) { |
---|
2030 | |
---|
2031 | html_engine_paste (e); |
---|
2032 | return; |
---|
2033 | |
---|
2034 | } else if (selection_data->selection == GDK_SELECTION_PRIMARY |
---|
2035 | && e->primary) { |
---|
2036 | HTMLObject *copy; |
---|
2037 | guint len = 0; |
---|
2038 | |
---|
2039 | copy = html_object_op_copy (e->primary, NULL, e, NULL, NULL, &len); |
---|
2040 | html_engine_paste_object (e, copy, len); |
---|
2041 | |
---|
2042 | return; |
---|
2043 | } |
---|
2044 | } |
---|
2045 | |
---|
2046 | /* **** IMPORTANT **** Check to see if retrieval succeeded */ |
---|
2047 | /* If we have more selection types we can ask for, try the next one, |
---|
2048 | until there are none left */ |
---|
2049 | if (selection_data->length < 0) { |
---|
2050 | gint type = GTK_HTML (widget)->priv->selection_type; |
---|
2051 | |
---|
2052 | /* now, try again with next selection type */ |
---|
2053 | if (!gtk_html_request_paste (GTK_HTML (widget), selection_data->selection, type + 1, time, as_cite)) |
---|
2054 | g_warning ("Selection retrieval failed\n"); |
---|
2055 | return; |
---|
2056 | } |
---|
2057 | |
---|
2058 | /* Make sure we got the data in the expected form */ |
---|
2059 | if ((selection_data->type != gdk_atom_intern ("UTF8_STRING", FALSE)) |
---|
2060 | && (selection_data->type != GDK_SELECTION_TYPE_STRING) |
---|
2061 | && (selection_data->type != gdk_atom_intern ("COMPOUND_TEXT", FALSE)) |
---|
2062 | && (selection_data->type != gdk_atom_intern ("TEXT", FALSE)) |
---|
2063 | && (selection_data->type != gdk_atom_intern ("text/html", FALSE))) { |
---|
2064 | g_warning ("Selection \"STRING\" was not returned as strings!\n"); |
---|
2065 | } else if (selection_data->length > 0) { |
---|
2066 | gchar *utf8 = NULL; |
---|
2067 | if (selection_data->type == gdk_atom_intern ("text/html", FALSE)) { |
---|
2068 | guint len = (guint)selection_data->length; |
---|
2069 | guchar *data = selection_data->data; |
---|
2070 | |
---|
2071 | /* |
---|
2072 | * FIXME This hack decides the charset of the selection. It seems that |
---|
2073 | * mozilla/netscape alway use ucs2 for text/html |
---|
2074 | * and openoffice.org seems to always use utf8 so we try to validate |
---|
2075 | * the string as utf8 and if that fails we assume it is ucs2 |
---|
2076 | */ |
---|
2077 | |
---|
2078 | if (len > 1 && |
---|
2079 | !g_utf8_validate (data, len - 1, NULL)) { |
---|
2080 | utf8 = ucs2_to_utf8_with_bom_check (data, len); |
---|
2081 | d_s (g_warning ("UCS-2 selection = %s", utf8);) |
---|
2082 | } else if (len > 0) { |
---|
2083 | d_s (g_warning ("UTF-8 selection (%d) = %s", len, data);) |
---|
2084 | |
---|
2085 | utf8 = g_malloc0 (len + 1); |
---|
2086 | memcpy (utf8, data, len); |
---|
2087 | } else { |
---|
2088 | g_warning ("unable to determine selection charset"); |
---|
2089 | return; |
---|
2090 | } |
---|
2091 | |
---|
2092 | if (as_cite) { |
---|
2093 | char *cite; |
---|
2094 | |
---|
2095 | cite = g_strdup_printf ("<br><blockquote type=\"cite\">%s</blockquote>", utf8); |
---|
2096 | |
---|
2097 | g_free (utf8); |
---|
2098 | utf8 = cite; |
---|
2099 | } |
---|
2100 | |
---|
2101 | if (utf8) |
---|
2102 | gtk_html_insert_html (GTK_HTML (widget), utf8); |
---|
2103 | else |
---|
2104 | g_warning ("selection was empty"); |
---|
2105 | |
---|
2106 | g_free (utf8); |
---|
2107 | } else if ((utf8 = gtk_selection_data_get_text (selection_data))) { |
---|
2108 | if (as_cite) { |
---|
2109 | char *encoded; |
---|
2110 | |
---|
2111 | /* FIXME there has to be a cleaner way to do this */ |
---|
2112 | encoded = html_encode_entities (utf8, g_utf8_strlen (utf8, -1), NULL); |
---|
2113 | g_free (utf8); |
---|
2114 | utf8 = g_strdup_printf ("<br><pre><blockquote type=\"cite\">%s</blockquote></pre>", |
---|
2115 | encoded); |
---|
2116 | g_free (encoded); |
---|
2117 | gtk_html_insert_html (GTK_HTML (widget), utf8); |
---|
2118 | } else { |
---|
2119 | html_engine_paste_text (e, utf8, g_utf8_strlen (utf8, -1)); |
---|
2120 | } |
---|
2121 | if (HTML_IS_TEXT (e->cursor->object)) |
---|
2122 | html_text_magic_link (HTML_TEXT (e->cursor->object), e, |
---|
2123 | html_object_get_length (e->cursor->object)); |
---|
2124 | |
---|
2125 | g_free (utf8); |
---|
2126 | } |
---|
2127 | return; |
---|
2128 | } |
---|
2129 | |
---|
2130 | if (html_engine_get_editable (e)) |
---|
2131 | html_engine_paste (e); |
---|
2132 | } |
---|
2133 | |
---|
2134 | gint |
---|
2135 | gtk_html_request_paste (GtkHTML *html, GdkAtom selection, gint type, gint32 time, gboolean as_cite) |
---|
2136 | { |
---|
2137 | GdkAtom format_atom; |
---|
2138 | static char *formats[] = {"text/html", "UTF8_STRING", "COMPOUND_TEXT", "TEXT", "STRING"}; |
---|
2139 | |
---|
2140 | if (type >= sizeof (formats) / sizeof (formats[0])) { |
---|
2141 | /* we have now tried all the slection types we support */ |
---|
2142 | html->priv->selection_type = -1; |
---|
2143 | if (html_engine_get_editable (html->engine)) |
---|
2144 | html_engine_paste (html->engine); |
---|
2145 | return FALSE; |
---|
2146 | } |
---|
2147 | |
---|
2148 | html->priv->selection_type = type; |
---|
2149 | html->priv->selection_as_cite = as_cite; |
---|
2150 | |
---|
2151 | format_atom = gdk_atom_intern (formats [type], FALSE); |
---|
2152 | |
---|
2153 | if (format_atom == GDK_NONE) { |
---|
2154 | g_warning("Could not get requested atom\n"); |
---|
2155 | } |
---|
2156 | /* And request the format target for the required selection */ |
---|
2157 | gtk_selection_convert (GTK_WIDGET (html), selection, format_atom, |
---|
2158 | time); |
---|
2159 | return TRUE; |
---|
2160 | } |
---|
2161 | |
---|
2162 | |
---|
2163 | static gint |
---|
2164 | selection_clear_event (GtkWidget *widget, |
---|
2165 | GdkEventSelection *event) |
---|
2166 | { |
---|
2167 | GtkHTML *html; |
---|
2168 | |
---|
2169 | if (! gtk_selection_clear (widget, event)) |
---|
2170 | return FALSE; |
---|
2171 | |
---|
2172 | html = GTK_HTML (widget); |
---|
2173 | |
---|
2174 | if (!html_engine_get_editable (html->engine)) { |
---|
2175 | html_engine_disable_selection (html->engine); |
---|
2176 | html->in_selection = FALSE; |
---|
2177 | } |
---|
2178 | |
---|
2179 | return TRUE; |
---|
2180 | } |
---|
2181 | |
---|
2182 | |
---|
2183 | static void |
---|
2184 | set_adjustments (GtkLayout *layout, |
---|
2185 | GtkAdjustment *hadj, |
---|
2186 | GtkAdjustment *vadj) |
---|
2187 | { |
---|
2188 | GtkHTML *html = GTK_HTML(layout); |
---|
2189 | |
---|
2190 | connect_adjustments (html, hadj, vadj); |
---|
2191 | |
---|
2192 | if (parent_class->set_scroll_adjustments) |
---|
2193 | (* parent_class->set_scroll_adjustments) (layout, hadj, vadj); |
---|
2194 | } |
---|
2195 | |
---|
2196 | |
---|
2197 | /* Initialization. */ |
---|
2198 | static void |
---|
2199 | client_notify_spell_widget (GConfClient* client, guint cnxn_id, GConfEntry* entry, gpointer user_data) |
---|
2200 | { |
---|
2201 | GtkHTML *html = (GtkHTML *) user_data; |
---|
2202 | GtkHTMLClass *klass = GTK_HTML_CLASS (GTK_WIDGET_GET_CLASS (html)); |
---|
2203 | GtkHTMLClassProperties *prop = klass->properties; |
---|
2204 | gchar *tkey; |
---|
2205 | |
---|
2206 | g_assert (client == gconf_client); |
---|
2207 | g_assert (entry->key); |
---|
2208 | tkey = strrchr (entry->key, '/'); |
---|
2209 | g_assert (tkey); |
---|
2210 | |
---|
2211 | if (!strcmp (tkey, "/language")) { |
---|
2212 | g_free (prop->language); |
---|
2213 | prop->language = g_strdup (gconf_client_get_string (client, entry->key, NULL)); |
---|
2214 | if (!html->engine->language) |
---|
2215 | gtk_html_api_set_language (html); |
---|
2216 | } |
---|
2217 | } |
---|
2218 | |
---|
2219 | static GtkHTMLClassProperties * |
---|
2220 | get_class_properties (GtkHTML *html) |
---|
2221 | { |
---|
2222 | GtkHTMLClass *klass; |
---|
2223 | |
---|
2224 | klass = GTK_HTML_CLASS (GTK_WIDGET_GET_CLASS (html)); |
---|
2225 | if (!klass->properties) { |
---|
2226 | klass->properties = gtk_html_class_properties_new (GTK_WIDGET (html)); |
---|
2227 | |
---|
2228 | if (!gconf_is_initialized ()) { |
---|
2229 | char *argv[] = { "gtkhtml", NULL }; |
---|
2230 | |
---|
2231 | g_warning ("gconf is not initialized, please call gconf_init before using GtkHTML library. " |
---|
2232 | "Meanwhile it's initialized by gtkhtml itself."); |
---|
2233 | gconf_init (1, argv, &gconf_error); |
---|
2234 | if (gconf_error) |
---|
2235 | g_error ("gconf error: %s\n", gconf_error->message); |
---|
2236 | } |
---|
2237 | |
---|
2238 | gconf_client = gconf_client_get_default (); |
---|
2239 | if (!gconf_client) |
---|
2240 | g_error ("cannot create gconf_client\n"); |
---|
2241 | gconf_client_add_dir (gconf_client, GTK_HTML_GCONF_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, &gconf_error); |
---|
2242 | if (gconf_error) |
---|
2243 | g_error ("gconf error: %s\n", gconf_error->message); |
---|
2244 | gconf_client_add_dir (gconf_client, GNOME_SPELL_GCONF_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, &gconf_error); |
---|
2245 | if (gconf_error) |
---|
2246 | g_error ("gconf error: %s\n", gconf_error->message); |
---|
2247 | gtk_html_class_properties_load (klass->properties, gconf_client); |
---|
2248 | |
---|
2249 | if (gconf_error) |
---|
2250 | g_warning ("gconf error: %s\n", gconf_error->message); |
---|
2251 | } |
---|
2252 | |
---|
2253 | return klass->properties; |
---|
2254 | } |
---|
2255 | |
---|
2256 | static void |
---|
2257 | set_focus_child (GtkContainer *containter, GtkWidget *w) |
---|
2258 | { |
---|
2259 | HTMLObject *o = NULL; |
---|
2260 | |
---|
2261 | while (w && !(o = g_object_get_data (G_OBJECT (w), "embeddedelement"))) |
---|
2262 | w = w->parent; |
---|
2263 | |
---|
2264 | if (o && !html_object_is_frame (o)) |
---|
2265 | html_engine_set_focus_object (GTK_HTML (containter)->engine, o, 0); |
---|
2266 | |
---|
2267 | (*GTK_CONTAINER_CLASS (parent_class)->set_focus_child) (containter, w); |
---|
2268 | } |
---|
2269 | |
---|
2270 | static gboolean |
---|
2271 | focus (GtkWidget *w, GtkDirectionType direction) |
---|
2272 | { |
---|
2273 | HTMLEngine *e = GTK_HTML (w)->engine; |
---|
2274 | |
---|
2275 | if (html_engine_get_editable (e)) { |
---|
2276 | gboolean rv; |
---|
2277 | |
---|
2278 | rv = (*GTK_WIDGET_CLASS (parent_class)->focus) (w, direction); |
---|
2279 | html_engine_set_focus (GTK_HTML (w)->engine, rv); |
---|
2280 | return rv; |
---|
2281 | } |
---|
2282 | |
---|
2283 | /* Reset selection. */ |
---|
2284 | if (e->shift_selection || e->mark) { |
---|
2285 | html_engine_disable_selection (e); |
---|
2286 | html_engine_edit_selection_updater_schedule (e->selection_updater); |
---|
2287 | e->shift_selection = FALSE; |
---|
2288 | } |
---|
2289 | |
---|
2290 | if (html_engine_focus (e, direction) && e->focus_object) { |
---|
2291 | gint offset; |
---|
2292 | HTMLObject *obj = html_engine_get_focus_object (e, &offset); |
---|
2293 | gint x1, y1, x2, y2, xo, yo; |
---|
2294 | |
---|
2295 | xo = e->x_offset; |
---|
2296 | yo = e->y_offset; |
---|
2297 | |
---|
2298 | if (HTML_IS_TEXT (obj)) { |
---|
2299 | if (!html_text_get_link_rectangle (HTML_TEXT (obj), e->painter, offset, &x1, &y1, &x2, &y2)) |
---|
2300 | return FALSE; |
---|
2301 | } else { |
---|
2302 | html_object_calc_abs_position (obj, &x1, &y1); |
---|
2303 | y2 = y1 + obj->descent; |
---|
2304 | x2 = x1 + obj->width; |
---|
2305 | y1 -= obj->ascent; |
---|
2306 | } |
---|
2307 | |
---|
2308 | /* printf ("child pos: %d,%d x %d,%d\n", x1, y1, x2, y2); */ |
---|
2309 | |
---|
2310 | if (x2 > e->x_offset + e->width) |
---|
2311 | e->x_offset = x2 - e->width; |
---|
2312 | if (x1 < e->x_offset) |
---|
2313 | e->x_offset = x1; |
---|
2314 | if (e->width > 2*RIGHT_BORDER && e->x_offset == x2 - e->width) |
---|
2315 | e->x_offset = MIN (x2 - e->width + RIGHT_BORDER + 1, |
---|
2316 | html_engine_get_doc_width (e) - e->width); |
---|
2317 | if (e->width > 2*LEFT_BORDER && e->x_offset >= x1) |
---|
2318 | e->x_offset = MAX (x1 - LEFT_BORDER, 0); |
---|
2319 | |
---|
2320 | if (y2 >= e->y_offset + e->height) |
---|
2321 | e->y_offset = y2 - e->height + 1; |
---|
2322 | if (y1 < e->y_offset) |
---|
2323 | e->y_offset = y1; |
---|
2324 | if (e->height > 2*BOTTOM_BORDER && e->y_offset == y2 - e->height + 1) |
---|
2325 | e->y_offset = MIN (y2 - e->height + BOTTOM_BORDER + 1, |
---|
2326 | html_engine_get_doc_height (e) - e->height); |
---|
2327 | if (e->height > 2*TOP_BORDER && e->y_offset >= y1) |
---|
2328 | e->y_offset = MAX (y1 - TOP_BORDER, 0); |
---|
2329 | |
---|
2330 | if (e->x_offset != xo) |
---|
2331 | gtk_adjustment_set_value (GTK_LAYOUT (w)->hadjustment, (gfloat) e->x_offset); |
---|
2332 | if (e->y_offset != yo) |
---|
2333 | gtk_adjustment_set_value (GTK_LAYOUT (w)->vadjustment, (gfloat) e->y_offset); |
---|
2334 | /* printf ("engine pos: %d,%d x %d,%d\n", |
---|
2335 | e->x_offset, e->y_offset, e->x_offset + e->width, e->y_offset + e->height); */ |
---|
2336 | |
---|
2337 | if (!GTK_WIDGET_HAS_FOCUS (w) && !html_object_is_embedded (obj)) |
---|
2338 | gtk_widget_grab_focus (w); |
---|
2339 | if (e->caret_mode) |
---|
2340 | html_engine_jump_to_object (e, obj, offset); |
---|
2341 | |
---|
2342 | return TRUE; |
---|
2343 | } |
---|
2344 | |
---|
2345 | return FALSE; |
---|
2346 | } |
---|
2347 | |
---|
2348 | /* dnd begin */ |
---|
2349 | |
---|
2350 | static void |
---|
2351 | drag_begin (GtkWidget *widget, GdkDragContext *context) |
---|
2352 | { |
---|
2353 | HTMLInterval *i; |
---|
2354 | HTMLObject *o; |
---|
2355 | |
---|
2356 | /* printf ("drag_begin\n"); */ |
---|
2357 | GTK_HTML (widget)->priv->dnd_real_object = o = GTK_HTML (widget)->priv->dnd_object; |
---|
2358 | GTK_HTML (widget)->priv->dnd_real_object_offset = GTK_HTML (widget)->priv->dnd_object_offset; |
---|
2359 | GTK_HTML (widget)->priv->dnd_in_progress = TRUE; |
---|
2360 | |
---|
2361 | i = html_interval_new (o, o, 0, html_object_get_length (o)); |
---|
2362 | html_engine_select_interval (GTK_HTML (widget)->engine, i); |
---|
2363 | } |
---|
2364 | |
---|
2365 | static void |
---|
2366 | drag_end (GtkWidget *widget, GdkDragContext *context) |
---|
2367 | { |
---|
2368 | /* printf ("drag_end\n"); */ |
---|
2369 | GTK_HTML (widget)->priv->dnd_in_progress = FALSE; |
---|
2370 | } |
---|
2371 | |
---|
2372 | static void |
---|
2373 | drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time) |
---|
2374 | { |
---|
2375 | /* printf ("drag_data_get\n"); */ |
---|
2376 | switch (info) { |
---|
2377 | case DND_TARGET_TYPE_MOZILLA_URL: |
---|
2378 | case DND_TARGET_TYPE_TEXT_URI_LIST: |
---|
2379 | /* printf ("\ttext/uri-list\n"); */ |
---|
2380 | case DND_TARGET_TYPE_TEXT_HTML: |
---|
2381 | case DND_TARGET_TYPE_TEXT_PLAIN: |
---|
2382 | case DND_TARGET_TYPE_UTF8_STRING: |
---|
2383 | case DND_TARGET_TYPE_STRING: { |
---|
2384 | HTMLObject *obj = GTK_HTML (widget)->priv->dnd_real_object; |
---|
2385 | gint offset = GTK_HTML (widget)->priv->dnd_real_object_offset; |
---|
2386 | const gchar *url, *target; |
---|
2387 | gchar *complete_url; |
---|
2388 | |
---|
2389 | /* printf ("\ttext/plain\n"); */ |
---|
2390 | if (obj) { |
---|
2391 | /* printf ("obj %p\n", obj); */ |
---|
2392 | url = html_object_get_url (obj, offset); |
---|
2393 | target = html_object_get_target (obj, offset); |
---|
2394 | if (url && *url) { |
---|
2395 | |
---|
2396 | complete_url = g_strconcat (url, target && *target ? "#" : NULL, target, NULL); |
---|
2397 | |
---|
2398 | if (info == DND_TARGET_TYPE_MOZILLA_URL) { |
---|
2399 | /* MOZ_URL is in UCS-2 but in format 8. BROKEN! |
---|
2400 | * |
---|
2401 | * The data contains the URL, a \n, then the |
---|
2402 | * title of the web page. |
---|
2403 | */ |
---|
2404 | char *ucs2; |
---|
2405 | char *utf8; |
---|
2406 | int written_len; |
---|
2407 | |
---|
2408 | if (HTML_IS_TEXT (obj)) { |
---|
2409 | Link *link = html_text_get_link_at_offset (HTML_TEXT (obj), offset); |
---|
2410 | char *text; |
---|
2411 | |
---|
2412 | g_return_if_fail (link); |
---|
2413 | text = g_strndup (HTML_TEXT (obj)->text + link->start_index, link->end_index - link->start_index); |
---|
2414 | utf8 = g_strconcat (complete_url, "\n", text, NULL); |
---|
2415 | } else |
---|
2416 | utf8 = g_strconcat (complete_url, "\n", complete_url, NULL); |
---|
2417 | |
---|
2418 | ucs2 = g_convert (utf8, strlen (utf8), "UCS-2", "UTF-8", NULL, &written_len, NULL); |
---|
2419 | gtk_selection_data_set (selection_data, selection_data->target, 8, |
---|
2420 | ucs2, written_len); |
---|
2421 | g_free (utf8); |
---|
2422 | g_free (complete_url); |
---|
2423 | GTK_HTML (widget)->priv->dnd_url = ucs2; |
---|
2424 | } else { |
---|
2425 | gtk_selection_data_set (selection_data, selection_data->target, 8, |
---|
2426 | complete_url, strlen (complete_url)); |
---|
2427 | /* printf ("complete URL %s\n", complete_url); */ |
---|
2428 | GTK_HTML (widget)->priv->dnd_url = complete_url; |
---|
2429 | } |
---|
2430 | } |
---|
2431 | } |
---|
2432 | } |
---|
2433 | break; |
---|
2434 | } |
---|
2435 | } |
---|
2436 | |
---|
2437 | static void |
---|
2438 | drag_data_delete (GtkWidget *widget, GdkDragContext *context) |
---|
2439 | { |
---|
2440 | g_free (GTK_HTML (widget)->priv->dnd_url); |
---|
2441 | GTK_HTML (widget)->priv->dnd_url = NULL; |
---|
2442 | } |
---|
2443 | |
---|
2444 | static gchar * |
---|
2445 | next_uri (guchar **uri_list, gint *len, gint *list_len) |
---|
2446 | { |
---|
2447 | guchar *uri, *begin; |
---|
2448 | |
---|
2449 | begin = *uri_list; |
---|
2450 | *len = 0; |
---|
2451 | while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) { |
---|
2452 | (*uri_list) ++; |
---|
2453 | (*len) ++; |
---|
2454 | (*list_len) --; |
---|
2455 | } |
---|
2456 | |
---|
2457 | uri = g_strndup (begin, *len); |
---|
2458 | |
---|
2459 | while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) { |
---|
2460 | (*uri_list) ++; |
---|
2461 | (*list_len) --; |
---|
2462 | } |
---|
2463 | |
---|
2464 | return uri; |
---|
2465 | } |
---|
2466 | |
---|
2467 | static gchar *known_protocols [] = { |
---|
2468 | "http://", |
---|
2469 | "ftp://", |
---|
2470 | "nntp://", |
---|
2471 | "news://", |
---|
2472 | "mailto:", |
---|
2473 | "file:", |
---|
2474 | NULL |
---|
2475 | }; |
---|
2476 | |
---|
2477 | static HTMLObject * |
---|
2478 | new_obj_from_uri (HTMLEngine *e, char *uri, char *title, gint len) |
---|
2479 | { |
---|
2480 | gint i; |
---|
2481 | |
---|
2482 | if (!strncmp (uri, "file:", 5)) { |
---|
2483 | if (!HTML_IS_PLAIN_PAINTER(e->painter)) { |
---|
2484 | GdkPixbuf *pixbuf = NULL; |
---|
2485 | char *img_path = g_filename_from_uri (uri, NULL, NULL); |
---|
2486 | if (img_path) { |
---|
2487 | pixbuf = gdk_pixbuf_new_from_file(img_path, NULL); |
---|
2488 | g_free(img_path); |
---|
2489 | } |
---|
2490 | if (pixbuf) { |
---|
2491 | g_object_unref (pixbuf); |
---|
2492 | return html_image_new (html_engine_get_image_factory (e), uri, |
---|
2493 | NULL, NULL, -1, -1, FALSE, FALSE, 0, |
---|
2494 | html_colorset_get_color (e->settings->color_set, HTMLTextColor), |
---|
2495 | HTML_VALIGN_BOTTOM, TRUE); |
---|
2496 | } |
---|
2497 | } |
---|
2498 | } |
---|
2499 | |
---|
2500 | for (i = 0; known_protocols [i]; i++) { |
---|
2501 | if (!strncmp (uri, known_protocols [i], strlen (known_protocols [i]))) { |
---|
2502 | if (!title) |
---|
2503 | title = uri; |
---|
2504 | return html_engine_new_link (e, title, len, uri); |
---|
2505 | } |
---|
2506 | } |
---|
2507 | |
---|
2508 | return NULL; |
---|
2509 | } |
---|
2510 | |
---|
2511 | static void |
---|
2512 | move_before_paste (GtkWidget *widget, gint x, gint y) |
---|
2513 | { |
---|
2514 | HTMLEngine *engine = GTK_HTML (widget)->engine; |
---|
2515 | |
---|
2516 | if (html_engine_is_selection_active (engine)) { |
---|
2517 | HTMLObject *obj; |
---|
2518 | guint offset; |
---|
2519 | |
---|
2520 | obj = html_engine_get_object_at (engine, x, y, &offset, FALSE); |
---|
2521 | if (!html_engine_point_in_selection (engine, obj, offset)) { |
---|
2522 | html_engine_disable_selection (engine); |
---|
2523 | html_engine_edit_selection_updater_update_now (engine->selection_updater); |
---|
2524 | } |
---|
2525 | } |
---|
2526 | if (!html_engine_is_selection_active (engine)) { |
---|
2527 | |
---|
2528 | html_engine_jump_at (engine, x, y); |
---|
2529 | gtk_html_update_styles (GTK_HTML (widget)); |
---|
2530 | } |
---|
2531 | } |
---|
2532 | |
---|
2533 | static void |
---|
2534 | drag_data_received (GtkWidget *widget, GdkDragContext *context, |
---|
2535 | gint x, gint y, GtkSelectionData *selection_data, guint info, guint time) |
---|
2536 | { |
---|
2537 | HTMLEngine *engine = GTK_HTML (widget)->engine; |
---|
2538 | gboolean pasted = FALSE; |
---|
2539 | |
---|
2540 | /* printf ("drag data received at %d,%d\n", x, y); */ |
---|
2541 | |
---|
2542 | if (!selection_data->data || selection_data->length < 0 || !html_engine_get_editable (engine)) |
---|
2543 | return; |
---|
2544 | |
---|
2545 | gdk_window_get_pointer (GTK_LAYOUT (widget)->bin_window, &x, &y, NULL); |
---|
2546 | move_before_paste (widget, x, y); |
---|
2547 | |
---|
2548 | switch (info) { |
---|
2549 | case DND_TARGET_TYPE_TEXT_PLAIN: |
---|
2550 | case DND_TARGET_TYPE_UTF8_STRING: |
---|
2551 | case DND_TARGET_TYPE_STRING: |
---|
2552 | case DND_TARGET_TYPE_TEXT_HTML: |
---|
2553 | selection_received (widget, selection_data, time); |
---|
2554 | pasted = TRUE; |
---|
2555 | break; |
---|
2556 | case DND_TARGET_TYPE_MOZILLA_URL : { |
---|
2557 | HTMLObject *obj; |
---|
2558 | char *utf8, *title; |
---|
2559 | |
---|
2560 | /* MOZ_URL is in UCS-2 but in format 8. BROKEN! |
---|
2561 | * |
---|
2562 | * The data contains the URL, a \n, then the |
---|
2563 | * title of the web page. |
---|
2564 | */ |
---|
2565 | |
---|
2566 | if (selection_data->format != 8 || |
---|
2567 | selection_data->length == 0 || |
---|
2568 | (selection_data->length % 2) != 0) { |
---|
2569 | g_printerr (_("Mozilla url dropped on Composer had wrong format (%d) or length (%d)\n"), |
---|
2570 | selection_data->format, |
---|
2571 | selection_data->length); |
---|
2572 | /* get out of the switch */ |
---|
2573 | break; |
---|
2574 | } |
---|
2575 | |
---|
2576 | utf8 = ucs2_to_utf8_with_bom_check (selection_data->data, selection_data->length); |
---|
2577 | title = strchr (utf8, '\n'); |
---|
2578 | if (title) { |
---|
2579 | *title = 0; |
---|
2580 | title ++; |
---|
2581 | } |
---|
2582 | |
---|
2583 | html_undo_level_begin (engine->undo, "Dropped URI(s)", "Remove Dropped URI(s)"); |
---|
2584 | |
---|
2585 | obj = new_obj_from_uri (engine, utf8, (HTML_IS_PLAIN_PAINTER (engine->painter) && context->action <= GDK_ACTION_COPY) ? utf8 : title, -1); |
---|
2586 | if (obj) { |
---|
2587 | html_engine_paste_object (engine, obj, html_object_get_length (obj)); |
---|
2588 | pasted = TRUE; |
---|
2589 | } |
---|
2590 | html_undo_level_end (engine->undo); |
---|
2591 | g_free (utf8); |
---|
2592 | } |
---|
2593 | break; |
---|
2594 | |
---|
2595 | case DND_TARGET_TYPE_TEXT_URI_LIST: { |
---|
2596 | HTMLObject *obj; |
---|
2597 | gint list_len, len; |
---|
2598 | gchar *uri; |
---|
2599 | |
---|
2600 | html_undo_level_begin (engine->undo, "Dropped URI(s)", "Remove Dropped URI(s)"); |
---|
2601 | list_len = selection_data->length; |
---|
2602 | do { |
---|
2603 | uri = next_uri (&selection_data->data, &len, &list_len); |
---|
2604 | obj = new_obj_from_uri (engine, uri, NULL, -1); |
---|
2605 | if (obj) { |
---|
2606 | html_engine_paste_object (engine, obj, html_object_get_length (obj)); |
---|
2607 | pasted = TRUE; |
---|
2608 | } |
---|
2609 | } while (list_len); |
---|
2610 | html_undo_level_end (engine->undo); |
---|
2611 | } |
---|
2612 | break; |
---|
2613 | } |
---|
2614 | gtk_drag_finish (context, pasted, FALSE, time); |
---|
2615 | } |
---|
2616 | |
---|
2617 | static gboolean |
---|
2618 | drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time) |
---|
2619 | { |
---|
2620 | GdkWindow *window = widget->window; |
---|
2621 | |
---|
2622 | if (!gtk_html_get_editable (GTK_HTML (widget))) |
---|
2623 | return FALSE; |
---|
2624 | |
---|
2625 | gdk_window_get_pointer (GTK_LAYOUT (widget)->bin_window, &x, &y, NULL); |
---|
2626 | |
---|
2627 | html_engine_disable_selection (GTK_HTML (widget)->engine); |
---|
2628 | html_engine_jump_at (GTK_HTML (widget)->engine, x, y); |
---|
2629 | html_engine_show_cursor (GTK_HTML (widget)->engine); |
---|
2630 | |
---|
2631 | mouse_change_pos (widget, window, x, y, 0); |
---|
2632 | |
---|
2633 | return TRUE; |
---|
2634 | } |
---|
2635 | |
---|
2636 | /* dnd end */ |
---|
2637 | |
---|
2638 | static void |
---|
2639 | read_key_theme (GtkHTMLClass *html_class) |
---|
2640 | { |
---|
2641 | gchar *key_theme; |
---|
2642 | |
---|
2643 | key_theme = gconf_client_get_string (gconf_client_get_default (), "/desktop/gnome/interface/gtk_key_theme", NULL); |
---|
2644 | html_class->use_emacs_bindings = key_theme && !strcmp (key_theme, "Emacs"); |
---|
2645 | g_free (key_theme); |
---|
2646 | } |
---|
2647 | |
---|
2648 | static void |
---|
2649 | client_notify_key_theme (GConfClient* client, guint cnxn_id, GConfEntry* entry, gpointer data) |
---|
2650 | { |
---|
2651 | read_key_theme ((GtkHTMLClass *) data); |
---|
2652 | } |
---|
2653 | |
---|
2654 | static void |
---|
2655 | client_notify_monospace_font (GConfClient* client, guint cnxn_id, GConfEntry* entry, gpointer data) |
---|
2656 | { |
---|
2657 | GtkHTML *html = (GtkHTML *) data; |
---|
2658 | HTMLEngine *e = html->engine; |
---|
2659 | if (e && e->painter) { |
---|
2660 | gtk_html_set_fonts (html, e->painter); |
---|
2661 | html_engine_refresh_fonts (e); |
---|
2662 | } |
---|
2663 | } |
---|
2664 | |
---|
2665 | static void |
---|
2666 | gtk_html_class_init (GtkHTMLClass *klass) |
---|
2667 | { |
---|
2668 | GObjectClass *gobject_class; |
---|
2669 | GtkHTMLClass *html_class; |
---|
2670 | GtkWidgetClass *widget_class; |
---|
2671 | GtkObjectClass *object_class; |
---|
2672 | GtkLayoutClass *layout_class; |
---|
2673 | GtkContainerClass *container_class; |
---|
2674 | |
---|
2675 | html_class = (GtkHTMLClass *) klass; |
---|
2676 | gobject_class = (GObjectClass *) klass; |
---|
2677 | widget_class = (GtkWidgetClass *) klass; |
---|
2678 | object_class = (GtkObjectClass *) klass; |
---|
2679 | layout_class = (GtkLayoutClass *) klass; |
---|
2680 | container_class = (GtkContainerClass *) klass; |
---|
2681 | |
---|
2682 | object_class->destroy = destroy; |
---|
2683 | |
---|
2684 | parent_class = gtk_type_class (GTK_TYPE_LAYOUT); |
---|
2685 | |
---|
2686 | signals [TITLE_CHANGED] = |
---|
2687 | g_signal_new ("title_changed", |
---|
2688 | G_TYPE_FROM_CLASS (object_class), |
---|
2689 | G_SIGNAL_RUN_FIRST, |
---|
2690 | G_STRUCT_OFFSET (GtkHTMLClass, title_changed), |
---|
2691 | NULL, NULL, |
---|
2692 | g_cclosure_marshal_VOID__STRING, |
---|
2693 | G_TYPE_NONE, 1, |
---|
2694 | G_TYPE_STRING); |
---|
2695 | signals [URL_REQUESTED] = |
---|
2696 | g_signal_new ("url_requested", |
---|
2697 | G_TYPE_FROM_CLASS (object_class), |
---|
2698 | G_SIGNAL_RUN_FIRST, |
---|
2699 | G_STRUCT_OFFSET (GtkHTMLClass, url_requested), |
---|
2700 | NULL, NULL, |
---|
2701 | html_g_cclosure_marshal_VOID__STRING_POINTER, |
---|
2702 | G_TYPE_NONE, 2, |
---|
2703 | G_TYPE_STRING, |
---|
2704 | G_TYPE_POINTER); |
---|
2705 | signals [LOAD_DONE] = |
---|
2706 | g_signal_new ("load_done", |
---|
2707 | G_TYPE_FROM_CLASS (object_class), |
---|
2708 | G_SIGNAL_RUN_FIRST, |
---|
2709 | G_STRUCT_OFFSET (GtkHTMLClass, load_done), |
---|
2710 | NULL, NULL, |
---|
2711 | g_cclosure_marshal_VOID__VOID, |
---|
2712 | G_TYPE_NONE, 0); |
---|
2713 | signals [LINK_CLICKED] = |
---|
2714 | g_signal_new ("link_clicked", |
---|
2715 | G_TYPE_FROM_CLASS (object_class), |
---|
2716 | G_SIGNAL_RUN_FIRST, |
---|
2717 | G_STRUCT_OFFSET (GtkHTMLClass, link_clicked), |
---|
2718 | NULL, NULL, |
---|
2719 | g_cclosure_marshal_VOID__STRING, |
---|
2720 | G_TYPE_NONE, 1, |
---|
2721 | G_TYPE_STRING); |
---|
2722 | signals [SET_BASE] = |
---|
2723 | g_signal_new ("set_base", |
---|
2724 | G_TYPE_FROM_CLASS (object_class), |
---|
2725 | G_SIGNAL_RUN_FIRST, |
---|
2726 | G_STRUCT_OFFSET (GtkHTMLClass, set_base), |
---|
2727 | NULL, NULL, |
---|
2728 | g_cclosure_marshal_VOID__STRING, |
---|
2729 | G_TYPE_NONE, 1, |
---|
2730 | G_TYPE_STRING); |
---|
2731 | signals [SET_BASE_TARGET] = |
---|
2732 | g_signal_new ("set_base_target", |
---|
2733 | G_TYPE_FROM_CLASS (object_class), |
---|
2734 | G_SIGNAL_RUN_FIRST, |
---|
2735 | G_STRUCT_OFFSET (GtkHTMLClass, set_base_target), |
---|
2736 | NULL, NULL, |
---|
2737 | g_cclosure_marshal_VOID__STRING, |
---|
2738 | G_TYPE_NONE, 1, |
---|
2739 | G_TYPE_STRING); |
---|
2740 | |
---|
2741 | signals [ON_URL] = |
---|
2742 | g_signal_new ("on_url", |
---|
2743 | G_TYPE_FROM_CLASS (object_class), |
---|
2744 | G_SIGNAL_RUN_FIRST, |
---|
2745 | G_STRUCT_OFFSET (GtkHTMLClass, on_url), |
---|
2746 | NULL, NULL, |
---|
2747 | g_cclosure_marshal_VOID__STRING, |
---|
2748 | G_TYPE_NONE, 1, |
---|
2749 | G_TYPE_STRING); |
---|
2750 | |
---|
2751 | signals [REDIRECT] = |
---|
2752 | g_signal_new ("redirect", |
---|
2753 | G_TYPE_FROM_CLASS (object_class), |
---|
2754 | G_SIGNAL_RUN_FIRST, |
---|
2755 | G_STRUCT_OFFSET (GtkHTMLClass, redirect), |
---|
2756 | NULL, NULL, |
---|
2757 | html_g_cclosure_marshal_VOID__POINTER_INT, |
---|
2758 | G_TYPE_NONE, 2, |
---|
2759 | G_TYPE_STRING, |
---|
2760 | G_TYPE_INT); |
---|
2761 | |
---|
2762 | signals [SUBMIT] = |
---|
2763 | g_signal_new ("submit", |
---|
2764 | G_TYPE_FROM_CLASS (object_class), |
---|
2765 | G_SIGNAL_RUN_FIRST, |
---|
2766 | G_STRUCT_OFFSET (GtkHTMLClass, submit), |
---|
2767 | NULL, NULL, |
---|
2768 | html_g_cclosure_marshal_VOID__STRING_STRING_STRING, |
---|
2769 | G_TYPE_NONE, 3, |
---|
2770 | G_TYPE_STRING, |
---|
2771 | G_TYPE_STRING, |
---|
2772 | G_TYPE_STRING); |
---|
2773 | |
---|
2774 | signals [OBJECT_REQUESTED] = |
---|
2775 | g_signal_new ("object_requested", |
---|
2776 | G_TYPE_FROM_CLASS (object_class), |
---|
2777 | G_SIGNAL_RUN_LAST, |
---|
2778 | G_STRUCT_OFFSET (GtkHTMLClass, object_requested), |
---|
2779 | NULL, NULL, |
---|
2780 | html_g_cclosure_marshal_BOOL__OBJECT, |
---|
2781 | G_TYPE_BOOLEAN, 1, |
---|
2782 | G_TYPE_OBJECT); |
---|
2783 | |
---|
2784 | signals [CURRENT_PARAGRAPH_STYLE_CHANGED] = |
---|
2785 | g_signal_new ("current_paragraph_style_changed", |
---|
2786 | G_TYPE_FROM_CLASS (object_class), |
---|
2787 | G_SIGNAL_RUN_FIRST, |
---|
2788 | G_STRUCT_OFFSET (GtkHTMLClass, current_paragraph_style_changed), |
---|
2789 | NULL, NULL, |
---|
2790 | g_cclosure_marshal_VOID__INT, |
---|
2791 | G_TYPE_NONE, 1, |
---|
2792 | G_TYPE_INT); |
---|
2793 | |
---|
2794 | signals [CURRENT_PARAGRAPH_INDENTATION_CHANGED] = |
---|
2795 | g_signal_new ("current_paragraph_indentation_changed", |
---|
2796 | G_TYPE_FROM_CLASS (object_class), |
---|
2797 | G_SIGNAL_RUN_FIRST, |
---|
2798 | G_STRUCT_OFFSET (GtkHTMLClass, current_paragraph_indentation_changed), |
---|
2799 | NULL, NULL, |
---|
2800 | g_cclosure_marshal_VOID__INT, |
---|
2801 | G_TYPE_NONE, 1, |
---|
2802 | G_TYPE_INT); |
---|
2803 | |
---|
2804 | signals [CURRENT_PARAGRAPH_ALIGNMENT_CHANGED] = |
---|
2805 | g_signal_new ("current_paragraph_alignment_changed", |
---|
2806 | G_TYPE_FROM_CLASS (object_class), |
---|
2807 | G_SIGNAL_RUN_FIRST, |
---|
2808 | G_STRUCT_OFFSET (GtkHTMLClass, current_paragraph_alignment_changed), |
---|
2809 | NULL, NULL, |
---|
2810 | g_cclosure_marshal_VOID__INT, |
---|
2811 | G_TYPE_NONE, 1, |
---|
2812 | G_TYPE_INT); |
---|
2813 | |
---|
2814 | signals [INSERTION_FONT_STYLE_CHANGED] = |
---|
2815 | g_signal_new ("insertion_font_style_changed", |
---|
2816 | G_TYPE_FROM_CLASS (object_class), |
---|
2817 | G_SIGNAL_RUN_FIRST, |
---|
2818 | G_STRUCT_OFFSET (GtkHTMLClass, insertion_font_style_changed), |
---|
2819 | NULL, NULL, |
---|
2820 | g_cclosure_marshal_VOID__INT, |
---|
2821 | G_TYPE_NONE, 1, |
---|
2822 | G_TYPE_INT); |
---|
2823 | |
---|
2824 | signals [INSERTION_COLOR_CHANGED] = |
---|
2825 | g_signal_new ("insertion_color_changed", |
---|
2826 | G_TYPE_FROM_CLASS (object_class), |
---|
2827 | G_SIGNAL_RUN_FIRST, |
---|
2828 | G_STRUCT_OFFSET (GtkHTMLClass, insertion_color_changed), |
---|
2829 | NULL, NULL, |
---|
2830 | g_cclosure_marshal_VOID__POINTER, |
---|
2831 | G_TYPE_NONE, 1, |
---|
2832 | G_TYPE_POINTER); |
---|
2833 | |
---|
2834 | signals [SIZE_CHANGED] = |
---|
2835 | g_signal_new ("size_changed", |
---|
2836 | G_TYPE_FROM_CLASS (object_class), |
---|
2837 | G_SIGNAL_RUN_FIRST, |
---|
2838 | G_STRUCT_OFFSET (GtkHTMLClass, size_changed), |
---|
2839 | NULL, NULL, |
---|
2840 | g_cclosure_marshal_VOID__VOID, |
---|
2841 | G_TYPE_NONE, 0); |
---|
2842 | signals [IFRAME_CREATED] = |
---|
2843 | g_signal_new ("iframe_created", |
---|
2844 | G_TYPE_FROM_CLASS (object_class), |
---|
2845 | G_SIGNAL_RUN_FIRST, |
---|
2846 | G_STRUCT_OFFSET (GtkHTMLClass, iframe_created), |
---|
2847 | NULL, NULL, |
---|
2848 | g_cclosure_marshal_VOID__OBJECT, |
---|
2849 | G_TYPE_NONE, 1, |
---|
2850 | GTK_TYPE_HTML); |
---|
2851 | |
---|
2852 | signals [SCROLL] = |
---|
2853 | g_signal_new ("scroll", |
---|
2854 | G_TYPE_FROM_CLASS (object_class), |
---|
2855 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
---|
2856 | G_STRUCT_OFFSET (GtkHTMLClass, scroll), |
---|
2857 | NULL, NULL, |
---|
2858 | html_g_cclosure_marshal_VOID__ENUM_ENUM_FLOAT, |
---|
2859 | G_TYPE_NONE, 3, |
---|
2860 | GTK_TYPE_ORIENTATION, |
---|
2861 | GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT); |
---|
2862 | |
---|
2863 | signals [CURSOR_MOVE] = |
---|
2864 | g_signal_new ("cursor_move", |
---|
2865 | G_TYPE_FROM_CLASS (object_class), |
---|
2866 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
---|
2867 | G_STRUCT_OFFSET (GtkHTMLClass, cursor_move), |
---|
2868 | NULL, NULL, |
---|
2869 | html_g_cclosure_marshal_VOID__ENUM_ENUM, |
---|
2870 | G_TYPE_NONE, 2, GTK_TYPE_DIRECTION_TYPE, GTK_TYPE_HTML_CURSOR_SKIP); |
---|
2871 | |
---|
2872 | signals [COMMAND] = |
---|
2873 | g_signal_new ("command", |
---|
2874 | G_TYPE_FROM_CLASS (object_class), |
---|
2875 | G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, |
---|
2876 | G_STRUCT_OFFSET (GtkHTMLClass, command), |
---|
2877 | NULL, NULL, |
---|
2878 | g_cclosure_marshal_VOID__ENUM, |
---|
2879 | G_TYPE_NONE, 1, GTK_TYPE_HTML_COMMAND); |
---|
2880 | |
---|
2881 | object_class->destroy = destroy; |
---|
2882 | |
---|
2883 | |
---|
2884 | #ifdef USE_PROPS |
---|
2885 | gobject_class->get_property = gtk_html_get_property; |
---|
2886 | gobject_class->set_property = gtk_html_set_property; |
---|
2887 | |
---|
2888 | g_object_class_install_property (gobject_class, |
---|
2889 | PROP_EDITABLE, |
---|
2890 | g_param_spec_boolean ("editable", |
---|
2891 | _("Editable"), |
---|
2892 | _("Whether the html can be edited"), |
---|
2893 | FALSE, |
---|
2894 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
2895 | g_object_class_install_property (gobject_class, |
---|
2896 | PROP_TITLE, |
---|
2897 | g_param_spec_string ("title", |
---|
2898 | _("Document Title"), |
---|
2899 | _("The title of the current document"), |
---|
2900 | NULL, |
---|
2901 | G_PARAM_WRITABLE | G_PARAM_READABLE)); |
---|
2902 | g_object_class_install_property (gobject_class, |
---|
2903 | PROP_DOCUMENT_BASE, |
---|
2904 | g_param_spec_string ("document_base", |
---|
2905 | _("Document Base"), |
---|
2906 | _("The base URL for relative references"), |
---|
2907 | NULL, |
---|
2908 | G_PARAM_WRITABLE | G_PARAM_READABLE)); |
---|
2909 | g_object_class_install_property (gobject_class, |
---|
2910 | PROP_TARGET_BASE, |
---|
2911 | g_param_spec_string ("target_base", |
---|
2912 | _("Target Base"), |
---|
2913 | _("The base URL of the targe frame"), |
---|
2914 | NULL, |
---|
2915 | G_PARAM_WRITABLE | G_PARAM_READABLE)); |
---|
2916 | |
---|
2917 | |
---|
2918 | #endif |
---|
2919 | |
---|
2920 | gtk_widget_class_install_style_property (widget_class, |
---|
2921 | g_param_spec_string ("fixed_font_name", |
---|
2922 | _("Fixed Width Font"), |
---|
2923 | _("The Monospace font to use for typewriter text"), |
---|
2924 | NULL, |
---|
2925 | G_PARAM_READABLE)); |
---|
2926 | |
---|
2927 | gtk_widget_class_install_style_property (widget_class, |
---|
2928 | g_param_spec_boxed ("link_color", |
---|
2929 | _("New Link Color"), |
---|
2930 | _("The color of new link elements"), |
---|
2931 | GDK_TYPE_COLOR, |
---|
2932 | G_PARAM_READABLE)); |
---|
2933 | gtk_widget_class_install_style_property (widget_class, |
---|
2934 | g_param_spec_boxed ("vlink_color", |
---|
2935 | _("Visited Link Color"), |
---|
2936 | _("The color of visited link elements"), |
---|
2937 | GDK_TYPE_COLOR, |
---|
2938 | G_PARAM_READABLE)); |
---|
2939 | gtk_widget_class_install_style_property (widget_class, |
---|
2940 | g_param_spec_boxed ("alink_color", |
---|
2941 | _("Active Link Color"), |
---|
2942 | _("The color of active link elements"), |
---|
2943 | GDK_TYPE_COLOR, |
---|
2944 | G_PARAM_READABLE)); |
---|
2945 | gtk_widget_class_install_style_property (widget_class, |
---|
2946 | g_param_spec_boxed ("spell_error_color", |
---|
2947 | _("Spelling Error Color"), |
---|
2948 | _("The color of the spelling error markers"), |
---|
2949 | GDK_TYPE_COLOR, |
---|
2950 | G_PARAM_READABLE)); |
---|
2951 | gtk_widget_class_install_style_property (widget_class, |
---|
2952 | g_param_spec_boxed ("cite_color", |
---|
2953 | _("Cite Quotation Color"), |
---|
2954 | _("The color of the cited text"), |
---|
2955 | GDK_TYPE_COLOR, |
---|
2956 | G_PARAM_READABLE)); |
---|
2957 | |
---|
2958 | |
---|
2959 | widget_class->realize = realize; |
---|
2960 | widget_class->unrealize = unrealize; |
---|
2961 | widget_class->style_set = style_set; |
---|
2962 | widget_class->key_press_event = key_press_event; |
---|
2963 | widget_class->key_release_event = key_release_event; |
---|
2964 | widget_class->expose_event = expose; |
---|
2965 | widget_class->size_request = gtk_html_size_request; |
---|
2966 | widget_class->size_allocate = size_allocate; |
---|
2967 | widget_class->motion_notify_event = motion_notify_event; |
---|
2968 | widget_class->visibility_notify_event = visibility_notify_event; |
---|
2969 | widget_class->hierarchy_changed = hierarchy_changed; |
---|
2970 | widget_class->button_press_event = button_press_event; |
---|
2971 | widget_class->button_release_event = button_release_event; |
---|
2972 | widget_class->focus_in_event = focus_in_event; |
---|
2973 | widget_class->focus_out_event = focus_out_event; |
---|
2974 | widget_class->enter_notify_event = enter_notify_event; |
---|
2975 | widget_class->selection_get = selection_get; |
---|
2976 | widget_class->selection_received = selection_received; |
---|
2977 | widget_class->selection_clear_event = selection_clear_event; |
---|
2978 | widget_class->drag_data_get = drag_data_get; |
---|
2979 | widget_class->drag_data_delete = drag_data_delete; |
---|
2980 | widget_class->drag_begin = drag_begin; |
---|
2981 | widget_class->drag_end = drag_end; |
---|
2982 | widget_class->drag_data_received = drag_data_received; |
---|
2983 | widget_class->drag_motion = drag_motion; |
---|
2984 | widget_class->focus = focus; |
---|
2985 | |
---|
2986 | container_class->set_focus_child = set_focus_child; |
---|
2987 | |
---|
2988 | layout_class->set_scroll_adjustments = set_adjustments; |
---|
2989 | |
---|
2990 | html_class->scroll = scroll; |
---|
2991 | html_class->cursor_move = cursor_move; |
---|
2992 | html_class->command = command; |
---|
2993 | |
---|
2994 | add_bindings (klass); |
---|
2995 | gtk_html_accessibility_init (); |
---|
2996 | |
---|
2997 | gtk_rc_parse (PREFIX "/share/" GTKHTML_RELEASE_STRING "/keybindingsrc.emacs"); |
---|
2998 | html_class->emacs_bindings = gtk_binding_set_find ("gtkhtml-bindings-emacs"); |
---|
2999 | read_key_theme (html_class); |
---|
3000 | gconf_client_notify_add (gconf_client_get_default (), "/desktop/gnome/interface/gtk_key_theme", |
---|
3001 | client_notify_key_theme, html_class, NULL, &gconf_error); |
---|
3002 | } |
---|
3003 | |
---|
3004 | static void |
---|
3005 | init_properties_widget (GtkHTML *html) |
---|
3006 | { |
---|
3007 | GtkHTMLClassProperties *prop; |
---|
3008 | |
---|
3009 | prop = get_class_properties (html); |
---|
3010 | |
---|
3011 | html->priv->notify_spell_id = gconf_client_notify_add (gconf_client, GNOME_SPELL_GCONF_DIR, |
---|
3012 | client_notify_spell_widget, html, NULL, &gconf_error); |
---|
3013 | if (gconf_error) { |
---|
3014 | g_warning ("gconf error: %s\n", gconf_error->message); |
---|
3015 | html->priv->notify_spell_id = 0; |
---|
3016 | } |
---|
3017 | } |
---|
3018 | |
---|
3019 | void |
---|
3020 | gtk_html_im_reset (GtkHTML *html) |
---|
3021 | { |
---|
3022 | if (!html->priv->im_block_reset) { |
---|
3023 | D_IM (printf ("IM reset requested\n");) |
---|
3024 | if (html->priv->need_im_reset) { |
---|
3025 | if (html->engine->freeze_count == 1) |
---|
3026 | html_engine_thaw_idle_flush (html->engine); |
---|
3027 | html->priv->need_im_reset = FALSE; |
---|
3028 | gtk_im_context_reset (html->priv->im_context); |
---|
3029 | D_IM (printf ("IM reset called\n");) |
---|
3030 | } |
---|
3031 | } |
---|
3032 | } |
---|
3033 | |
---|
3034 | static void |
---|
3035 | gtk_html_im_commit_cb (GtkIMContext *context, const gchar *str, GtkHTML *html) |
---|
3036 | { |
---|
3037 | gboolean state = html->priv->im_block_reset; |
---|
3038 | gint pos; |
---|
3039 | |
---|
3040 | if (html->priv->im_pre_len > 0) { |
---|
3041 | D_IM (printf ("IM delete last preedit %d + %d\n", html->priv->im_pre_pos, html->priv->im_pre_len);) |
---|
3042 | |
---|
3043 | html_undo_freeze (html->engine->undo); |
---|
3044 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos); |
---|
3045 | html_engine_set_mark (html->engine); |
---|
3046 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + html->priv->im_pre_len); |
---|
3047 | html_engine_delete (html->engine); |
---|
3048 | html->priv->im_pre_len = 0; |
---|
3049 | html_undo_thaw (html->engine->undo); |
---|
3050 | } |
---|
3051 | |
---|
3052 | pos = html->engine->cursor->position; |
---|
3053 | if (html->engine->mark && html->engine->mark->position > pos) |
---|
3054 | pos = html->engine->mark->position; |
---|
3055 | |
---|
3056 | html->priv->im_block_reset = TRUE; |
---|
3057 | D_IM (printf ("IM commit %s\n", str);) |
---|
3058 | html_engine_paste_text (html->engine, str, -1); |
---|
3059 | html->priv->im_block_reset = state; |
---|
3060 | |
---|
3061 | D_IM (printf ("IM commit pos: %d pre_pos: %d\n", pos, html->priv->im_pre_pos);) |
---|
3062 | if (html->priv->im_pre_pos >= pos) |
---|
3063 | html->priv->im_pre_pos += html->engine->cursor->position - pos; |
---|
3064 | } |
---|
3065 | |
---|
3066 | static void |
---|
3067 | gtk_html_im_preedit_start_cb (GtkIMContext *context, GtkHTML *html) |
---|
3068 | { |
---|
3069 | html->priv->im_pre_len = 0; |
---|
3070 | } |
---|
3071 | |
---|
3072 | static void |
---|
3073 | gtk_html_im_preedit_changed_cb (GtkIMContext *context, GtkHTML *html) |
---|
3074 | { |
---|
3075 | PangoAttrList *attrs; |
---|
3076 | gchar *preedit_string; |
---|
3077 | gint cursor_pos, initial_position; |
---|
3078 | gboolean state = html->priv->im_block_reset; |
---|
3079 | gboolean pop_selection = FALSE; |
---|
3080 | gint deleted = 0; |
---|
3081 | |
---|
3082 | D_IM (printf ("IM preedit changed cb [begin] cursor %d(%p) mark %d(%p) active: %d\n", |
---|
3083 | html->engine->cursor ? html->engine->cursor->position : 0, html->engine->cursor, |
---|
3084 | html->engine->mark ? html->engine->mark->position : 0, html->engine->mark, |
---|
3085 | html_engine_is_selection_active (html->engine));) |
---|
3086 | html->priv->im_block_reset = TRUE; |
---|
3087 | |
---|
3088 | if (html_engine_is_selection_active (html->engine)) { |
---|
3089 | D_IM (printf ("IM push selection\n");) |
---|
3090 | html_engine_selection_push (html->engine); |
---|
3091 | html_engine_disable_selection (html->engine); |
---|
3092 | html_engine_edit_selection_updater_update_now (html->engine->selection_updater); |
---|
3093 | pop_selection = TRUE; |
---|
3094 | } |
---|
3095 | initial_position = html->engine->cursor->position; |
---|
3096 | D_IM (printf ("IM initial position %d\n", initial_position);) |
---|
3097 | |
---|
3098 | html_undo_freeze (html->engine->undo); |
---|
3099 | |
---|
3100 | if (html->priv->im_pre_len > 0) { |
---|
3101 | D_IM (printf ("IM delete last preedit %d + %d\n", html->priv->im_pre_pos, html->priv->im_pre_len);) |
---|
3102 | |
---|
3103 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos); |
---|
3104 | html_engine_set_mark (html->engine); |
---|
3105 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + html->priv->im_pre_len); |
---|
3106 | html_engine_delete (html->engine); |
---|
3107 | deleted = html->priv->im_pre_len; |
---|
3108 | } else |
---|
3109 | html->priv->im_orig_style = html_engine_get_font_style (html->engine); |
---|
3110 | |
---|
3111 | gtk_im_context_get_preedit_string (html->priv->im_context, &preedit_string, &attrs, &cursor_pos); |
---|
3112 | |
---|
3113 | D_IM (printf ("IM preedit changed to %s\n", preedit_string);) |
---|
3114 | html->priv->im_pre_len = g_utf8_strlen (preedit_string, -1); |
---|
3115 | |
---|
3116 | if (html->priv->im_pre_len > 0) { |
---|
3117 | cursor_pos = CLAMP (cursor_pos, 0, html->priv->im_pre_len); |
---|
3118 | html->priv->im_pre_pos = html->engine->cursor->position; |
---|
3119 | html_engine_paste_text_with_extra_attributes (html->engine, preedit_string, html->priv->im_pre_len, attrs); |
---|
3120 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, html->priv->im_pre_pos + cursor_pos); |
---|
3121 | } else |
---|
3122 | html_engine_set_font_style (html->engine, 0, html->priv->im_orig_style); |
---|
3123 | g_free (preedit_string); |
---|
3124 | |
---|
3125 | if (pop_selection) { |
---|
3126 | gint position= html->engine->cursor->position, cpos, mpos; |
---|
3127 | D_IM (printf ("IM pop selection\n");) |
---|
3128 | g_assert (html_engine_selection_stack_top (html->engine, &cpos, &mpos)); |
---|
3129 | if (position < MAX (cpos, mpos) + html->priv->im_pre_len - deleted) |
---|
3130 | g_assert (html_engine_selection_stack_top_modify (html->engine, html->priv->im_pre_len - deleted)); |
---|
3131 | html_engine_selection_pop (html->engine); |
---|
3132 | } |
---|
3133 | /* that works for now, but idealy we should be able to have cursor positioned outside selection, so that preedit |
---|
3134 | cursor is in the right place */ |
---|
3135 | if (html->priv->im_pre_len == 0) |
---|
3136 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, |
---|
3137 | initial_position >= html->priv->im_pre_pos + deleted ? initial_position - deleted : initial_position); |
---|
3138 | |
---|
3139 | if (html->engine->freeze_count == 1) |
---|
3140 | html_engine_thaw_idle_flush (html->engine); |
---|
3141 | /* FIXME gtk_im_context_set_cursor_location (im_context, &area); */ |
---|
3142 | html->priv->im_block_reset = state; |
---|
3143 | |
---|
3144 | html_undo_thaw (html->engine->undo); |
---|
3145 | |
---|
3146 | D_IM (printf ("IM preedit changed cb [end] cursor %d(%p) mark %d(%p) active: %d\n", |
---|
3147 | html->engine->cursor ? html->engine->cursor->position : 0, html->engine->cursor, |
---|
3148 | html->engine->mark ? html->engine->mark->position : 0, html->engine->mark, |
---|
3149 | html_engine_is_selection_active (html->engine));) |
---|
3150 | } |
---|
3151 | |
---|
3152 | static gchar * |
---|
3153 | get_surrounding_text (HTMLEngine *e, gint *offset) |
---|
3154 | { |
---|
3155 | HTMLObject *o = e->cursor->object; |
---|
3156 | HTMLObject *prev; |
---|
3157 | gchar *text = NULL; |
---|
3158 | |
---|
3159 | if (!html_object_is_text (o)) { |
---|
3160 | if (e->cursor->offset == 0) { |
---|
3161 | prev = html_object_prev_not_slave (o); |
---|
3162 | if (html_object_is_text (prev)) { |
---|
3163 | o = prev; |
---|
3164 | } else |
---|
3165 | return NULL; |
---|
3166 | } else if (e->cursor->offset == html_object_get_length (e->cursor->object)) { |
---|
3167 | HTMLObject *next; |
---|
3168 | |
---|
3169 | next = html_object_next_not_slave (o); |
---|
3170 | if (html_object_is_text (next)) { |
---|
3171 | o = next; |
---|
3172 | } else |
---|
3173 | return NULL; |
---|
3174 | } |
---|
3175 | *offset = 0; |
---|
3176 | } else |
---|
3177 | *offset = e->cursor->offset; |
---|
3178 | |
---|
3179 | while ((prev = html_object_prev_not_slave (o)) && html_object_is_text (prev)) { |
---|
3180 | o = prev; |
---|
3181 | *offset += HTML_TEXT (o)->text_len; |
---|
3182 | } |
---|
3183 | |
---|
3184 | while (o) { |
---|
3185 | if (html_object_is_text (o)) |
---|
3186 | text = g_strconcat (text, HTML_TEXT (o)->text, NULL); |
---|
3187 | o = html_object_next_not_slave (o); |
---|
3188 | } |
---|
3189 | |
---|
3190 | return text; |
---|
3191 | } |
---|
3192 | |
---|
3193 | static gboolean |
---|
3194 | gtk_html_im_retrieve_surrounding_cb (GtkIMContext *context, GtkHTML *html) |
---|
3195 | { |
---|
3196 | gint offset; |
---|
3197 | |
---|
3198 | D_IM (printf ("IM gtk_html_im_retrieve_surrounding_cb\n");) |
---|
3199 | gtk_im_context_set_surrounding (context, get_surrounding_text (html->engine, &offset), -1, offset); |
---|
3200 | |
---|
3201 | return TRUE; |
---|
3202 | } |
---|
3203 | |
---|
3204 | static gboolean |
---|
3205 | gtk_html_im_delete_surrounding_cb (GtkIMContext *slave, gint offset, gint n_chars, GtkHTML *html) |
---|
3206 | { |
---|
3207 | D_IM (printf ("IM gtk_html_im_delete_surrounding_cb\n");) |
---|
3208 | if (html_engine_get_editable (html->engine) && !html_engine_is_selection_active (html->engine)) { |
---|
3209 | gint orig_position = html->engine->cursor->position; |
---|
3210 | |
---|
3211 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position + offset); |
---|
3212 | html_engine_set_mark (html->engine); |
---|
3213 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position + offset + n_chars); |
---|
3214 | html_engine_delete (html->engine); |
---|
3215 | if (offset >= 0) |
---|
3216 | html_cursor_jump_to_position_no_spell (html->engine->cursor, html->engine, orig_position); |
---|
3217 | } |
---|
3218 | return TRUE; |
---|
3219 | } |
---|
3220 | |
---|
3221 | static void |
---|
3222 | gtk_html_init (GtkHTML* html) |
---|
3223 | { |
---|
3224 | static const GtkTargetEntry targets[] = { |
---|
3225 | { "text/html", 0, TARGET_HTML }, |
---|
3226 | { "UTF8_STRING", 0, TARGET_UTF8_STRING }, |
---|
3227 | { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, |
---|
3228 | { "STRING", 0, TARGET_STRING }, |
---|
3229 | { "TEXT", 0, TARGET_TEXT } |
---|
3230 | }; |
---|
3231 | static const gint n_targets = sizeof(targets) / sizeof(targets[0]); |
---|
3232 | |
---|
3233 | GTK_WIDGET_SET_FLAGS (GTK_WIDGET (html), GTK_CAN_FOCUS); |
---|
3234 | GTK_WIDGET_SET_FLAGS (GTK_WIDGET (html), GTK_APP_PAINTABLE); |
---|
3235 | |
---|
3236 | html->editor_api = NULL; |
---|
3237 | html->debug = FALSE; |
---|
3238 | html->allow_selection = TRUE; |
---|
3239 | |
---|
3240 | html->pointer_url = NULL; |
---|
3241 | html->hand_cursor = gdk_cursor_new (GDK_HAND2); |
---|
3242 | html->ibeam_cursor = gdk_cursor_new (GDK_XTERM); |
---|
3243 | html->hadj_connection = 0; |
---|
3244 | html->vadj_connection = 0; |
---|
3245 | |
---|
3246 | html->selection_x1 = 0; |
---|
3247 | html->selection_y1 = 0; |
---|
3248 | |
---|
3249 | html->in_selection = FALSE; |
---|
3250 | html->in_selection_drag = FALSE; |
---|
3251 | |
---|
3252 | html->priv = g_new0 (GtkHTMLPrivate, 1); |
---|
3253 | html->priv->idle_handler_id = 0; |
---|
3254 | html->priv->scroll_timeout_id = 0; |
---|
3255 | html->priv->paragraph_style = GTK_HTML_PARAGRAPH_STYLE_NORMAL; |
---|
3256 | html->priv->paragraph_alignment = GTK_HTML_PARAGRAPH_ALIGNMENT_LEFT; |
---|
3257 | html->priv->paragraph_indentation = 0; |
---|
3258 | html->priv->insertion_font_style = GTK_HTML_FONT_STYLE_DEFAULT; |
---|
3259 | html->priv->selection_type = -1; |
---|
3260 | html->priv->selection_as_cite = FALSE; |
---|
3261 | html->priv->content_type = g_strdup ("html/text; charset=utf-8"); |
---|
3262 | html->priv->search_input_line = NULL; |
---|
3263 | html->priv->in_object_resize = FALSE; |
---|
3264 | html->priv->resize_cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER); |
---|
3265 | |
---|
3266 | gtk_selection_add_targets (GTK_WIDGET (html), |
---|
3267 | GDK_SELECTION_PRIMARY, |
---|
3268 | targets, n_targets); |
---|
3269 | gtk_selection_add_targets (GTK_WIDGET (html), |
---|
3270 | gdk_atom_intern ("CLIPBOARD", FALSE), |
---|
3271 | targets, n_targets); |
---|
3272 | |
---|
3273 | /* IM Context */ |
---|
3274 | html->priv->im_context = gtk_im_multicontext_new (); |
---|
3275 | html->priv->need_im_reset = FALSE; |
---|
3276 | html->priv->im_block_reset = FALSE; |
---|
3277 | html->priv->im_pre_len = 0; |
---|
3278 | |
---|
3279 | g_signal_connect (G_OBJECT (html->priv->im_context), "commit", |
---|
3280 | G_CALLBACK (gtk_html_im_commit_cb), html); |
---|
3281 | g_signal_connect (G_OBJECT (html->priv->im_context), "preedit_start", |
---|
3282 | G_CALLBACK (gtk_html_im_preedit_start_cb), html); |
---|
3283 | g_signal_connect (G_OBJECT (html->priv->im_context), "preedit_changed", |
---|
3284 | G_CALLBACK (gtk_html_im_preedit_changed_cb), html); |
---|
3285 | g_signal_connect (G_OBJECT (html->priv->im_context), "retrieve_surrounding", |
---|
3286 | G_CALLBACK (gtk_html_im_retrieve_surrounding_cb), html); |
---|
3287 | g_signal_connect (G_OBJECT (html->priv->im_context), "delete_surrounding", |
---|
3288 | G_CALLBACK (gtk_html_im_delete_surrounding_cb), html); |
---|
3289 | |
---|
3290 | html->priv->notify_monospace_font_id = |
---|
3291 | gconf_client_notify_add (gconf_client_get_default (), "/desktop/gnome/interface/monospace_font_name", |
---|
3292 | client_notify_monospace_font, html, NULL, &gconf_error); |
---|
3293 | |
---|
3294 | gtk_html_construct (html); |
---|
3295 | } |
---|
3296 | |
---|
3297 | GType |
---|
3298 | gtk_html_get_type (void) |
---|
3299 | { |
---|
3300 | static GType html_type = 0; |
---|
3301 | |
---|
3302 | if (!html_type) { |
---|
3303 | static const GTypeInfo html_info = { |
---|
3304 | sizeof (GtkHTMLClass), |
---|
3305 | NULL, /* base_init */ |
---|
3306 | NULL, /* base_finalize */ |
---|
3307 | (GClassInitFunc) gtk_html_class_init, |
---|
3308 | NULL, /* class_finalize */ |
---|
3309 | NULL, /* class_data */ |
---|
3310 | sizeof (GtkHTML), |
---|
3311 | 1, /* n_preallocs */ |
---|
3312 | (GInstanceInitFunc) gtk_html_init, |
---|
3313 | }; |
---|
3314 | |
---|
3315 | html_type = g_type_register_static (GTK_TYPE_LAYOUT, "GtkHTML", &html_info, 0); |
---|
3316 | } |
---|
3317 | |
---|
3318 | return html_type; |
---|
3319 | } |
---|
3320 | |
---|
3321 | /** |
---|
3322 | * gtk_html_new: |
---|
3323 | * @void: |
---|
3324 | * |
---|
3325 | * GtkHTML widget contructor. It creates an empty GtkHTML widget. |
---|
3326 | * |
---|
3327 | * Return value: A GtkHTML widget, newly created and empty. |
---|
3328 | **/ |
---|
3329 | |
---|
3330 | GtkWidget * |
---|
3331 | gtk_html_new (void) |
---|
3332 | { |
---|
3333 | GtkWidget *html; |
---|
3334 | |
---|
3335 | html = g_object_new (GTK_TYPE_HTML, NULL); |
---|
3336 | |
---|
3337 | return html; |
---|
3338 | } |
---|
3339 | |
---|
3340 | /** |
---|
3341 | * gtk_html_new_from_string: |
---|
3342 | * @str: A string containing HTML source. |
---|
3343 | * @len: A length of @str, if @len == -1 then it will be computed using strlen. |
---|
3344 | * |
---|
3345 | * GtkHTML widget constructor. It creates an new GtkHTML widget and loads HTML source from @str. |
---|
3346 | * It is intended for simple creation. For more complicated loading you probably want to use |
---|
3347 | * #GtkHTMLStream. See #gtk_html_begin. |
---|
3348 | * |
---|
3349 | * Return value: A GtkHTML widget, newly created, containing document loaded from input @str. |
---|
3350 | **/ |
---|
3351 | |
---|
3352 | GtkWidget * |
---|
3353 | gtk_html_new_from_string (const gchar *str, gint len) |
---|
3354 | { |
---|
3355 | GtkWidget *html; |
---|
3356 | |
---|
3357 | html = g_object_new (GTK_TYPE_HTML, NULL); |
---|
3358 | gtk_html_load_from_string (GTK_HTML (html), str, len); |
---|
3359 | |
---|
3360 | return html; |
---|
3361 | } |
---|
3362 | |
---|
3363 | void |
---|
3364 | gtk_html_construct (GtkHTML *html) |
---|
3365 | { |
---|
3366 | g_return_if_fail (html != NULL); |
---|
3367 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3368 | |
---|
3369 | html->engine = html_engine_new (GTK_WIDGET (html)); |
---|
3370 | html->iframe_parent = NULL; |
---|
3371 | |
---|
3372 | g_signal_connect (G_OBJECT (html->engine), "title_changed", |
---|
3373 | G_CALLBACK (html_engine_title_changed_cb), html); |
---|
3374 | g_signal_connect (G_OBJECT (html->engine), "set_base", |
---|
3375 | G_CALLBACK (html_engine_set_base_cb), html); |
---|
3376 | g_signal_connect (G_OBJECT (html->engine), "set_base_target", |
---|
3377 | G_CALLBACK (html_engine_set_base_target_cb), html); |
---|
3378 | g_signal_connect (G_OBJECT (html->engine), "load_done", |
---|
3379 | G_CALLBACK (html_engine_load_done_cb), html); |
---|
3380 | g_signal_connect (G_OBJECT (html->engine), "url_requested", |
---|
3381 | G_CALLBACK (html_engine_url_requested_cb), html); |
---|
3382 | g_signal_connect (G_OBJECT (html->engine), "draw_pending", |
---|
3383 | G_CALLBACK (html_engine_draw_pending_cb), html); |
---|
3384 | g_signal_connect (G_OBJECT (html->engine), "redirect", |
---|
3385 | G_CALLBACK (html_engine_redirect_cb), html); |
---|
3386 | g_signal_connect (G_OBJECT (html->engine), "submit", |
---|
3387 | G_CALLBACK (html_engine_submit_cb), html); |
---|
3388 | g_signal_connect (G_OBJECT (html->engine), "object_requested", |
---|
3389 | G_CALLBACK (html_engine_object_requested_cb), html); |
---|
3390 | |
---|
3391 | init_properties_widget (html); |
---|
3392 | } |
---|
3393 | |
---|
3394 | |
---|
3395 | void |
---|
3396 | gtk_html_enable_debug (GtkHTML *html, |
---|
3397 | gboolean debug) |
---|
3398 | { |
---|
3399 | g_return_if_fail (html != NULL); |
---|
3400 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3401 | |
---|
3402 | html->debug = debug; |
---|
3403 | } |
---|
3404 | |
---|
3405 | |
---|
3406 | void |
---|
3407 | gtk_html_allow_selection (GtkHTML *html, |
---|
3408 | gboolean allow) |
---|
3409 | { |
---|
3410 | g_return_if_fail (html != NULL); |
---|
3411 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3412 | |
---|
3413 | html->allow_selection = allow; |
---|
3414 | } |
---|
3415 | |
---|
3416 | |
---|
3417 | /** |
---|
3418 | * gtk_html_begin_full: |
---|
3419 | * @html: the GtkHTML widget to operate on. |
---|
3420 | * @target_frame: the string identifying the frame to load the data into |
---|
3421 | * @content_type: the content_type of the data that we will be loading |
---|
3422 | * @flags: the GtkHTMLBeginFlags that control the reload behavior handling |
---|
3423 | * |
---|
3424 | * Opens a new stream of type @content_type to the frame named @target_frame. |
---|
3425 | * the flags in @flags allow control over what data is reloaded. |
---|
3426 | * |
---|
3427 | * Returns: a new GtkHTMLStream to specified frame |
---|
3428 | */ |
---|
3429 | GtkHTMLStream * |
---|
3430 | gtk_html_begin_full (GtkHTML *html, |
---|
3431 | char *target_frame, |
---|
3432 | char *content_type, |
---|
3433 | GtkHTMLBeginFlags flags) |
---|
3434 | { |
---|
3435 | GtkHTMLStream *handle; |
---|
3436 | |
---|
3437 | g_return_val_if_fail (!gtk_html_get_editable (html), NULL); |
---|
3438 | |
---|
3439 | if (flags & GTK_HTML_BEGIN_BLOCK_UPDATES) |
---|
3440 | gtk_html_set_blocking (html, TRUE); |
---|
3441 | else |
---|
3442 | gtk_html_set_blocking (html, FALSE); |
---|
3443 | |
---|
3444 | if (flags & GTK_HTML_BEGIN_BLOCK_IMAGES) |
---|
3445 | gtk_html_set_images_blocking (html, TRUE); |
---|
3446 | else |
---|
3447 | gtk_html_set_images_blocking (html, FALSE); |
---|
3448 | |
---|
3449 | if (flags & GTK_HTML_BEGIN_KEEP_IMAGES) |
---|
3450 | gtk_html_images_ref (html); |
---|
3451 | |
---|
3452 | if (flags & GTK_HTML_BEGIN_KEEP_SCROLL) |
---|
3453 | html->engine->keep_scroll = TRUE; |
---|
3454 | else |
---|
3455 | html->engine->keep_scroll = FALSE; |
---|
3456 | |
---|
3457 | if (!content_type) |
---|
3458 | content_type = html->priv->content_type; |
---|
3459 | |
---|
3460 | handle = html_engine_begin (html->engine, content_type); |
---|
3461 | if (handle == NULL) |
---|
3462 | return NULL; |
---|
3463 | |
---|
3464 | html_engine_parse (html->engine); |
---|
3465 | |
---|
3466 | if (flags & GTK_HTML_BEGIN_KEEP_IMAGES) |
---|
3467 | gtk_html_images_unref (html); |
---|
3468 | |
---|
3469 | if (flags & GTK_HTML_BEGIN_KEEP_SCROLL) |
---|
3470 | html->engine->newPage = FALSE; |
---|
3471 | |
---|
3472 | return handle; |
---|
3473 | } |
---|
3474 | |
---|
3475 | /** |
---|
3476 | * gtk_html_begin: |
---|
3477 | * @html: the html widget to operate on. |
---|
3478 | * |
---|
3479 | * Opens a new stream to load new content into the GtkHTML widget @html. |
---|
3480 | * |
---|
3481 | * Returns: a new GtkHTMLStream to store new content. |
---|
3482 | **/ |
---|
3483 | GtkHTMLStream * |
---|
3484 | gtk_html_begin (GtkHTML *html) |
---|
3485 | { |
---|
3486 | g_return_val_if_fail (GTK_IS_HTML (html), NULL); |
---|
3487 | |
---|
3488 | return gtk_html_begin_full (html, NULL, html->priv->content_type, 0); |
---|
3489 | } |
---|
3490 | |
---|
3491 | /** |
---|
3492 | * gtk_html_begin_content: |
---|
3493 | * @html: the html widget to operate on. |
---|
3494 | * @content_type: a string listing the type of content to expect on the stream. |
---|
3495 | * |
---|
3496 | * Opens a new stream to load new content of type @content_type into |
---|
3497 | * the GtkHTML widget given in @html. |
---|
3498 | * |
---|
3499 | * Returns: a new GtkHTMLStream to store new content. |
---|
3500 | **/ |
---|
3501 | GtkHTMLStream * |
---|
3502 | gtk_html_begin_content (GtkHTML *html, gchar *content_type) |
---|
3503 | { |
---|
3504 | g_return_val_if_fail (! gtk_html_get_editable (html), NULL); |
---|
3505 | |
---|
3506 | return gtk_html_begin_full (html, NULL, NULL, 0); |
---|
3507 | } |
---|
3508 | |
---|
3509 | /** |
---|
3510 | * gtk_html_write: |
---|
3511 | * @html: the GtkHTML widget the stream belongs to (unused) |
---|
3512 | * @handle: the GkHTMLStream to write to. |
---|
3513 | * @buffer: the data to write to the stream. |
---|
3514 | * @size: the length of data to read from @buffer |
---|
3515 | * |
---|
3516 | * Writes @size bytes of @buffer to the stream pointed to by @stream. |
---|
3517 | **/ |
---|
3518 | void |
---|
3519 | gtk_html_write (GtkHTML *html, |
---|
3520 | GtkHTMLStream *handle, |
---|
3521 | const gchar *buffer, |
---|
3522 | size_t size) |
---|
3523 | { |
---|
3524 | gtk_html_stream_write (handle, buffer, size); |
---|
3525 | } |
---|
3526 | |
---|
3527 | /** |
---|
3528 | * gtk_html_end: |
---|
3529 | * @html: the GtkHTML widget the stream belongs to. |
---|
3530 | * @handle: the GtkHTMLStream to close. |
---|
3531 | * @status: the GtkHTMLStreamStatus representing the state of the stream when closed. |
---|
3532 | * |
---|
3533 | * Close the GtkHTMLStream represented by @stream and notify @html that is |
---|
3534 | * should not expect any more content from that stream. |
---|
3535 | **/ |
---|
3536 | void |
---|
3537 | gtk_html_end (GtkHTML *html, |
---|
3538 | GtkHTMLStream *handle, |
---|
3539 | GtkHTMLStreamStatus status) |
---|
3540 | { |
---|
3541 | gtk_html_stream_close (handle, status); |
---|
3542 | } |
---|
3543 | |
---|
3544 | /** |
---|
3545 | * gtk_html_stop: |
---|
3546 | * @html: the GtkHTML widget. |
---|
3547 | * |
---|
3548 | * Stop requesting any more data by url_requested signal. |
---|
3549 | **/ |
---|
3550 | void |
---|
3551 | gtk_html_stop (GtkHTML *html) |
---|
3552 | { |
---|
3553 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3554 | |
---|
3555 | html_engine_stop (html->engine); |
---|
3556 | } |
---|
3557 | |
---|
3558 | |
---|
3559 | /** |
---|
3560 | * gtk_html_get_title: |
---|
3561 | * @html: The GtkHTML widget. |
---|
3562 | * |
---|
3563 | * Retrieve the title of the document currently loaded in the GtkHTML widget. |
---|
3564 | * |
---|
3565 | * Returns: the title of the current document |
---|
3566 | **/ |
---|
3567 | const gchar * |
---|
3568 | gtk_html_get_title (GtkHTML *html) |
---|
3569 | { |
---|
3570 | g_return_val_if_fail (html != NULL, NULL); |
---|
3571 | g_return_val_if_fail (GTK_IS_HTML (html), NULL); |
---|
3572 | |
---|
3573 | if (html->engine->title == NULL) |
---|
3574 | return NULL; |
---|
3575 | |
---|
3576 | return html->engine->title->str; |
---|
3577 | } |
---|
3578 | |
---|
3579 | /** |
---|
3580 | * gtk_html_set_title: |
---|
3581 | * @html: The GtkHTML widget. |
---|
3582 | * |
---|
3583 | * Set the title of the document currently loaded in the GtkHTML widget. |
---|
3584 | * |
---|
3585 | **/ |
---|
3586 | void |
---|
3587 | gtk_html_set_title (GtkHTML *html, const char *title) |
---|
3588 | { |
---|
3589 | g_return_if_fail (html != NULL); |
---|
3590 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3591 | |
---|
3592 | html_engine_set_title (html->engine, title); |
---|
3593 | } |
---|
3594 | |
---|
3595 | |
---|
3596 | /** |
---|
3597 | * gtk_html_jump_to_anchor: |
---|
3598 | * @html: the GtkHTML widget. |
---|
3599 | * @anchor: a string containing the name of the anchor. |
---|
3600 | * |
---|
3601 | * Scroll the document display to show the HTML anchor listed in @anchor |
---|
3602 | * |
---|
3603 | * Returns: TRUE if the anchor is found, FALSE otherwise. |
---|
3604 | **/ |
---|
3605 | gboolean |
---|
3606 | gtk_html_jump_to_anchor (GtkHTML *html, |
---|
3607 | const gchar *anchor) |
---|
3608 | { |
---|
3609 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3610 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3611 | |
---|
3612 | return html_engine_goto_anchor (html->engine, anchor); |
---|
3613 | } |
---|
3614 | |
---|
3615 | |
---|
3616 | gboolean |
---|
3617 | gtk_html_save (GtkHTML *html, |
---|
3618 | GtkHTMLSaveReceiverFn receiver, |
---|
3619 | gpointer data) |
---|
3620 | { |
---|
3621 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3622 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3623 | g_return_val_if_fail (receiver != NULL, FALSE); |
---|
3624 | |
---|
3625 | return html_engine_save (html->engine, receiver, data); |
---|
3626 | } |
---|
3627 | |
---|
3628 | /** |
---|
3629 | * gtk_html_export: |
---|
3630 | * @html: the GtkHTML widget |
---|
3631 | * @content_type: the expected content_type |
---|
3632 | * @receiver: |
---|
3633 | * @user_data: pointer to maintain user state. |
---|
3634 | * |
---|
3635 | * Export the current document into the content type given by @content_type, |
---|
3636 | * by calling the function listed in @receiver data becomes avaiable. When @receiver is |
---|
3637 | * called @user_data is passed in as the user_data parameter. |
---|
3638 | * |
---|
3639 | * Returns: TRUE if the export was successfull, FALSE otherwise. |
---|
3640 | **/ |
---|
3641 | gboolean |
---|
3642 | gtk_html_export (GtkHTML *html, |
---|
3643 | const char *content_type, |
---|
3644 | GtkHTMLSaveReceiverFn receiver, |
---|
3645 | gpointer user_data) |
---|
3646 | { |
---|
3647 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3648 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3649 | g_return_val_if_fail (receiver != NULL, FALSE); |
---|
3650 | |
---|
3651 | if (strcmp (content_type, "text/html") == 0) { |
---|
3652 | return html_engine_save (html->engine, receiver, user_data); |
---|
3653 | } else if (strcmp (content_type, "text/plain") == 0) { |
---|
3654 | return html_engine_save_plain (html->engine, receiver, |
---|
3655 | user_data); |
---|
3656 | } else { |
---|
3657 | return FALSE; |
---|
3658 | } |
---|
3659 | } |
---|
3660 | |
---|
3661 | |
---|
3662 | |
---|
3663 | static void |
---|
3664 | gtk_html_update_scrollbars_on_resize (GtkHTML *html, |
---|
3665 | gdouble old_doc_width, gdouble old_doc_height, |
---|
3666 | gdouble old_width, gdouble old_height, |
---|
3667 | gboolean *changed_x, gboolean *changed_y) |
---|
3668 | { |
---|
3669 | GtkLayout *layout; |
---|
3670 | GtkAdjustment *vadj, *hadj; |
---|
3671 | gdouble doc_width, doc_height; |
---|
3672 | |
---|
3673 | /* printf ("update on resize\n"); */ |
---|
3674 | |
---|
3675 | layout = GTK_LAYOUT (html); |
---|
3676 | hadj = layout->hadjustment; |
---|
3677 | vadj = layout->vadjustment; |
---|
3678 | |
---|
3679 | doc_height = html_engine_get_doc_height (html->engine); |
---|
3680 | doc_width = html_engine_get_doc_width (html->engine); |
---|
3681 | |
---|
3682 | if (!html->engine->keep_scroll) { |
---|
3683 | if (old_doc_width - old_width > 0) { |
---|
3684 | html->engine->x_offset = (gint) (hadj->value * (doc_width - html->engine->width) |
---|
3685 | / (old_doc_width - old_width)); |
---|
3686 | |
---|
3687 | gtk_adjustment_set_value (hadj, html->engine->x_offset); |
---|
3688 | } |
---|
3689 | |
---|
3690 | if (old_doc_height - old_height > 0) { |
---|
3691 | html->engine->y_offset = (gint) (vadj->value * (doc_height - html->engine->height) |
---|
3692 | / (old_doc_height - old_height)); |
---|
3693 | gtk_adjustment_set_value (vadj, html->engine->y_offset); |
---|
3694 | } |
---|
3695 | } |
---|
3696 | } |
---|
3697 | |
---|
3698 | void |
---|
3699 | gtk_html_private_calc_scrollbars (GtkHTML *html, gboolean *changed_x, gboolean *changed_y) |
---|
3700 | { |
---|
3701 | GtkLayout *layout; |
---|
3702 | GtkAdjustment *vadj, *hadj; |
---|
3703 | gint width, height; |
---|
3704 | |
---|
3705 | if (!GTK_WIDGET_REALIZED (html)) |
---|
3706 | return; |
---|
3707 | |
---|
3708 | /* printf ("calc scrollbars\n"); */ |
---|
3709 | |
---|
3710 | height = html_engine_get_doc_height (html->engine); |
---|
3711 | width = html_engine_get_doc_width (html->engine); |
---|
3712 | |
---|
3713 | layout = GTK_LAYOUT (html); |
---|
3714 | hadj = layout->hadjustment; |
---|
3715 | vadj = layout->vadjustment; |
---|
3716 | |
---|
3717 | vadj->page_size = html->engine->height; |
---|
3718 | vadj->step_increment = 14; /* FIXME */ |
---|
3719 | vadj->page_increment = html->engine->height; |
---|
3720 | |
---|
3721 | if (vadj->value > height - html->engine->height) { |
---|
3722 | gtk_adjustment_set_value (vadj, height - html->engine->height); |
---|
3723 | if (changed_y) |
---|
3724 | *changed_y = TRUE; |
---|
3725 | } |
---|
3726 | |
---|
3727 | hadj->page_size = html->engine->width; |
---|
3728 | hadj->step_increment = 14; /* FIXME */ |
---|
3729 | hadj->page_increment = html->engine->width; |
---|
3730 | |
---|
3731 | if ((width != layout->width) || (height != layout->height)) { |
---|
3732 | g_signal_emit (html, signals [SIZE_CHANGED], 0); |
---|
3733 | gtk_layout_set_size (layout, width, height); |
---|
3734 | } |
---|
3735 | |
---|
3736 | if (hadj->value > width - html->engine->width || hadj->value > MAX_WIDGET_WIDTH - html->engine->width) { |
---|
3737 | gtk_adjustment_set_value (hadj, MIN (width - html->engine->width, MAX_WIDGET_WIDTH - html->engine->width)); |
---|
3738 | if (changed_x) |
---|
3739 | *changed_x = TRUE; |
---|
3740 | } |
---|
3741 | |
---|
3742 | } |
---|
3743 | |
---|
3744 | |
---|
3745 | |
---|
3746 | #ifdef USE_PROPS |
---|
3747 | static void |
---|
3748 | gtk_html_set_property (GObject *object, |
---|
3749 | guint prop_id, |
---|
3750 | const GValue *value, |
---|
3751 | GParamSpec *pspec) |
---|
3752 | { |
---|
3753 | GtkHTML *html = GTK_HTML (object); |
---|
3754 | |
---|
3755 | switch (prop_id) { |
---|
3756 | case PROP_EDITABLE: |
---|
3757 | gtk_html_set_editable (html, g_value_get_boolean (value)); |
---|
3758 | break; |
---|
3759 | case PROP_TITLE: |
---|
3760 | gtk_html_set_title (html, g_value_get_string (value)); |
---|
3761 | break; |
---|
3762 | case PROP_DOCUMENT_BASE: |
---|
3763 | gtk_html_set_base (html, g_value_get_string (value)); |
---|
3764 | break; |
---|
3765 | case PROP_TARGET_BASE: |
---|
3766 | /* This doesn't do anything yet */ |
---|
3767 | break; |
---|
3768 | default: |
---|
3769 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
---|
3770 | break; |
---|
3771 | } |
---|
3772 | } |
---|
3773 | |
---|
3774 | static void |
---|
3775 | gtk_html_get_property (GObject *object, |
---|
3776 | guint prop_id, |
---|
3777 | GValue *value, |
---|
3778 | GParamSpec *pspec) |
---|
3779 | { |
---|
3780 | GtkHTML *html = GTK_HTML (object); |
---|
3781 | |
---|
3782 | switch (prop_id) { |
---|
3783 | case PROP_EDITABLE: |
---|
3784 | g_value_set_boolean (value, gtk_html_get_editable (html)); |
---|
3785 | break; |
---|
3786 | case PROP_TITLE: |
---|
3787 | g_value_set_static_string (value, gtk_html_get_title (html)); |
---|
3788 | break; |
---|
3789 | case PROP_DOCUMENT_BASE: |
---|
3790 | g_value_set_static_string (value, gtk_html_get_base (html)); |
---|
3791 | break; |
---|
3792 | case PROP_TARGET_BASE: |
---|
3793 | g_value_set_static_string (value, gtk_html_get_base (html)); |
---|
3794 | break; |
---|
3795 | default: |
---|
3796 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
---|
3797 | break; |
---|
3798 | } |
---|
3799 | } |
---|
3800 | #endif |
---|
3801 | |
---|
3802 | void |
---|
3803 | gtk_html_set_editable (GtkHTML *html, |
---|
3804 | gboolean editable) |
---|
3805 | { |
---|
3806 | g_return_if_fail (html != NULL); |
---|
3807 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3808 | |
---|
3809 | html_engine_set_editable (html->engine, editable); |
---|
3810 | |
---|
3811 | if (editable) |
---|
3812 | gtk_html_update_styles (html); |
---|
3813 | } |
---|
3814 | |
---|
3815 | gboolean |
---|
3816 | gtk_html_get_editable (const GtkHTML *html) |
---|
3817 | { |
---|
3818 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3819 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3820 | |
---|
3821 | return html_engine_get_editable (html->engine); |
---|
3822 | } |
---|
3823 | |
---|
3824 | void |
---|
3825 | gtk_html_set_inline_spelling (GtkHTML *html, |
---|
3826 | gboolean inline_spell) |
---|
3827 | { |
---|
3828 | g_return_if_fail (html != NULL); |
---|
3829 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3830 | |
---|
3831 | html->priv->inline_spelling = inline_spell; |
---|
3832 | |
---|
3833 | if (gtk_html_get_editable (html) && html->priv->inline_spelling) |
---|
3834 | html_engine_spell_check (html->engine); |
---|
3835 | else |
---|
3836 | html_engine_clear_spell_check (html->engine); |
---|
3837 | } |
---|
3838 | |
---|
3839 | gboolean |
---|
3840 | gtk_html_get_inline_spelling (const GtkHTML *html) |
---|
3841 | { |
---|
3842 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3843 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3844 | |
---|
3845 | return html->priv->inline_spelling; |
---|
3846 | } |
---|
3847 | |
---|
3848 | void |
---|
3849 | gtk_html_set_magic_links (GtkHTML *html, |
---|
3850 | gboolean links) |
---|
3851 | { |
---|
3852 | g_return_if_fail (html != NULL); |
---|
3853 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3854 | |
---|
3855 | html->priv->magic_links = links; |
---|
3856 | } |
---|
3857 | |
---|
3858 | gboolean |
---|
3859 | gtk_html_get_magic_links (const GtkHTML *html) |
---|
3860 | { |
---|
3861 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3862 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3863 | |
---|
3864 | return html->priv->magic_links; |
---|
3865 | } |
---|
3866 | |
---|
3867 | void |
---|
3868 | gtk_html_set_magic_smileys (GtkHTML *html, |
---|
3869 | gboolean smile) |
---|
3870 | { |
---|
3871 | g_return_if_fail (html != NULL); |
---|
3872 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3873 | |
---|
3874 | html->priv->magic_smileys = smile; |
---|
3875 | } |
---|
3876 | |
---|
3877 | gboolean |
---|
3878 | gtk_html_get_magic_smileys (const GtkHTML *html) |
---|
3879 | { |
---|
3880 | g_return_val_if_fail (html != NULL, FALSE); |
---|
3881 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3882 | |
---|
3883 | return html->priv->magic_smileys; |
---|
3884 | } |
---|
3885 | |
---|
3886 | static void |
---|
3887 | frame_set_animate (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
3888 | { |
---|
3889 | if (HTML_IS_FRAME (o)) { |
---|
3890 | html_image_factory_set_animate (GTK_HTML (HTML_FRAME (o)->html)->engine->image_factory, |
---|
3891 | *(gboolean *)data); |
---|
3892 | } else if (HTML_IS_IFRAME (o)) { |
---|
3893 | html_image_factory_set_animate (GTK_HTML (HTML_IFRAME (o)->html)->engine->image_factory, |
---|
3894 | *(gboolean *)data); |
---|
3895 | } |
---|
3896 | } |
---|
3897 | |
---|
3898 | void |
---|
3899 | gtk_html_set_caret_mode(GtkHTML * html, gboolean caret_mode) |
---|
3900 | { |
---|
3901 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3902 | g_return_if_fail (HTML_IS_ENGINE (html->engine)); |
---|
3903 | |
---|
3904 | set_caret_mode(html->engine, caret_mode); |
---|
3905 | } |
---|
3906 | |
---|
3907 | gboolean |
---|
3908 | gtk_html_get_caret_mode(const GtkHTML *html) |
---|
3909 | { |
---|
3910 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3911 | g_return_val_if_fail (HTML_IS_ENGINE (html->engine), FALSE); |
---|
3912 | |
---|
3913 | return html->engine->caret_mode; |
---|
3914 | } |
---|
3915 | |
---|
3916 | void |
---|
3917 | gtk_html_set_animate (GtkHTML *html, gboolean animate) |
---|
3918 | { |
---|
3919 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3920 | g_return_if_fail (HTML_IS_ENGINE (html->engine)); |
---|
3921 | |
---|
3922 | html_image_factory_set_animate (html->engine->image_factory, animate); |
---|
3923 | if (html->engine->clue) |
---|
3924 | html_object_forall (html->engine->clue, html->engine, frame_set_animate, &animate); |
---|
3925 | } |
---|
3926 | |
---|
3927 | gboolean |
---|
3928 | gtk_html_get_animate (const GtkHTML *html) |
---|
3929 | { |
---|
3930 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
3931 | g_return_val_if_fail (HTML_IS_ENGINE (html->engine), FALSE); |
---|
3932 | |
---|
3933 | return html_image_factory_get_animate (html->engine->image_factory); |
---|
3934 | } |
---|
3935 | |
---|
3936 | void |
---|
3937 | gtk_html_load_empty (GtkHTML *html) |
---|
3938 | { |
---|
3939 | g_return_if_fail (html != NULL); |
---|
3940 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3941 | |
---|
3942 | html_engine_load_empty (html->engine); |
---|
3943 | } |
---|
3944 | |
---|
3945 | void |
---|
3946 | gtk_html_load_from_string (GtkHTML *html, const gchar *str, gint len) |
---|
3947 | { |
---|
3948 | GtkHTMLStream *stream; |
---|
3949 | |
---|
3950 | stream = gtk_html_begin_content (html, "text/html; charset=utf-8"); |
---|
3951 | gtk_html_stream_write (stream, str, (len == -1) ? strlen (str) : len); |
---|
3952 | gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); |
---|
3953 | } |
---|
3954 | |
---|
3955 | void |
---|
3956 | gtk_html_set_base (GtkHTML *html, const char *url) |
---|
3957 | { |
---|
3958 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3959 | |
---|
3960 | g_free (html->priv->base_url); |
---|
3961 | html->priv->base_url = g_strdup (url); |
---|
3962 | } |
---|
3963 | |
---|
3964 | const char * |
---|
3965 | gtk_html_get_base (GtkHTML *html) |
---|
3966 | { |
---|
3967 | g_return_val_if_fail (GTK_IS_HTML (html), NULL); |
---|
3968 | |
---|
3969 | return html->priv->base_url; |
---|
3970 | } |
---|
3971 | |
---|
3972 | |
---|
3973 | /* Printing. */ |
---|
3974 | |
---|
3975 | void |
---|
3976 | gtk_html_print (GtkHTML *html, |
---|
3977 | GnomePrintContext *print_context) |
---|
3978 | { |
---|
3979 | g_return_if_fail (html != NULL); |
---|
3980 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3981 | |
---|
3982 | html_engine_print (html->engine, print_context); |
---|
3983 | } |
---|
3984 | |
---|
3985 | void |
---|
3986 | gtk_html_print_with_header_footer (GtkHTML *html, GnomePrintContext *print_context, |
---|
3987 | gdouble header_height, gdouble footer_height, |
---|
3988 | GtkHTMLPrintCallback header_print, GtkHTMLPrintCallback footer_print, gpointer user_data) |
---|
3989 | { |
---|
3990 | g_return_if_fail (html != NULL); |
---|
3991 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
3992 | |
---|
3993 | html_engine_print_with_header_footer (html->engine, print_context, |
---|
3994 | header_height, footer_height, header_print, footer_print, user_data); |
---|
3995 | } |
---|
3996 | |
---|
3997 | |
---|
3998 | /* Editing. */ |
---|
3999 | |
---|
4000 | void |
---|
4001 | gtk_html_set_paragraph_style (GtkHTML *html, |
---|
4002 | GtkHTMLParagraphStyle style) |
---|
4003 | { |
---|
4004 | HTMLClueFlowStyle current_style; |
---|
4005 | HTMLClueFlowStyle clueflow_style; |
---|
4006 | HTMLListType item_type; |
---|
4007 | HTMLListType cur_item_type; |
---|
4008 | |
---|
4009 | g_return_if_fail (html != NULL); |
---|
4010 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4011 | |
---|
4012 | /* FIXME precondition: check if it's a valid style. */ |
---|
4013 | |
---|
4014 | paragraph_style_to_clueflow_style (style, &clueflow_style, &item_type); |
---|
4015 | |
---|
4016 | html_engine_get_current_clueflow_style (html->engine, ¤t_style, &cur_item_type); |
---|
4017 | if (!html_engine_is_selection_active (html->engine) && current_style == clueflow_style |
---|
4018 | && (current_style != HTML_CLUEFLOW_STYLE_LIST_ITEM || item_type == cur_item_type)) |
---|
4019 | return; |
---|
4020 | |
---|
4021 | if (! html_engine_set_clueflow_style (html->engine, clueflow_style, item_type, 0, 0, NULL, |
---|
4022 | HTML_ENGINE_SET_CLUEFLOW_STYLE, HTML_UNDO_UNDO, TRUE)) |
---|
4023 | return; |
---|
4024 | |
---|
4025 | html->priv->paragraph_style = style; |
---|
4026 | |
---|
4027 | g_signal_emit (html, signals[CURRENT_PARAGRAPH_STYLE_CHANGED], 0, style); |
---|
4028 | queue_draw (html); |
---|
4029 | } |
---|
4030 | |
---|
4031 | GtkHTMLParagraphStyle |
---|
4032 | gtk_html_get_paragraph_style (GtkHTML *html) |
---|
4033 | { |
---|
4034 | HTMLClueFlowStyle style; |
---|
4035 | HTMLListType item_type; |
---|
4036 | |
---|
4037 | html_engine_get_current_clueflow_style (html->engine, &style, &item_type); |
---|
4038 | |
---|
4039 | return clueflow_style_to_paragraph_style (style, item_type); |
---|
4040 | } |
---|
4041 | |
---|
4042 | guint |
---|
4043 | gtk_html_get_paragraph_indentation (GtkHTML *html) |
---|
4044 | { |
---|
4045 | return html_engine_get_current_clueflow_indentation (html->engine); |
---|
4046 | } |
---|
4047 | |
---|
4048 | void |
---|
4049 | gtk_html_set_indent (GtkHTML *html, |
---|
4050 | GByteArray *levels) |
---|
4051 | { |
---|
4052 | g_return_if_fail (html != NULL); |
---|
4053 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4054 | |
---|
4055 | html_engine_set_clueflow_style (html->engine, 0, 0, 0, |
---|
4056 | levels ? levels->len : 0, |
---|
4057 | levels ? levels->data : NULL, |
---|
4058 | HTML_ENGINE_SET_CLUEFLOW_INDENTATION, HTML_UNDO_UNDO, TRUE); |
---|
4059 | |
---|
4060 | gtk_html_update_styles (html); |
---|
4061 | } |
---|
4062 | |
---|
4063 | static void |
---|
4064 | gtk_html_modify_indent_by_delta (GtkHTML *html, |
---|
4065 | gint delta, guint8 *levels) |
---|
4066 | { |
---|
4067 | g_return_if_fail (html != NULL); |
---|
4068 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4069 | |
---|
4070 | html_engine_set_clueflow_style (html->engine, 0, 0, 0, delta, levels, |
---|
4071 | HTML_ENGINE_SET_CLUEFLOW_INDENTATION_DELTA, HTML_UNDO_UNDO, TRUE); |
---|
4072 | |
---|
4073 | gtk_html_update_styles (html); |
---|
4074 | } |
---|
4075 | |
---|
4076 | void |
---|
4077 | gtk_html_indent_push_level (GtkHTML *html, HTMLListType level_type) |
---|
4078 | { |
---|
4079 | guint8 type = (guint8)level_type; |
---|
4080 | gtk_html_modify_indent_by_delta (html, +1, &type); |
---|
4081 | } |
---|
4082 | |
---|
4083 | void |
---|
4084 | gtk_html_indent_pop_level (GtkHTML *html) |
---|
4085 | { |
---|
4086 | gtk_html_modify_indent_by_delta (html, -1, NULL); |
---|
4087 | } |
---|
4088 | |
---|
4089 | void |
---|
4090 | gtk_html_set_font_style (GtkHTML *html, |
---|
4091 | GtkHTMLFontStyle and_mask, |
---|
4092 | GtkHTMLFontStyle or_mask) |
---|
4093 | { |
---|
4094 | g_return_if_fail (html != NULL); |
---|
4095 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4096 | |
---|
4097 | if (html_engine_set_font_style (html->engine, and_mask, or_mask)) |
---|
4098 | g_signal_emit (html, signals [INSERTION_FONT_STYLE_CHANGED], 0, html->engine->insertion_font_style); |
---|
4099 | } |
---|
4100 | |
---|
4101 | void |
---|
4102 | gtk_html_set_color (GtkHTML *html, HTMLColor *color) |
---|
4103 | { |
---|
4104 | g_return_if_fail (html != NULL); |
---|
4105 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4106 | |
---|
4107 | if (html_engine_set_color (html->engine, color)) |
---|
4108 | g_signal_emit (html, signals [INSERTION_COLOR_CHANGED], 0, html->engine->insertion_font_style); |
---|
4109 | } |
---|
4110 | |
---|
4111 | void |
---|
4112 | gtk_html_toggle_font_style (GtkHTML *html, |
---|
4113 | GtkHTMLFontStyle style) |
---|
4114 | { |
---|
4115 | g_return_if_fail (html != NULL); |
---|
4116 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4117 | |
---|
4118 | if (html_engine_toggle_font_style (html->engine, style)) |
---|
4119 | g_signal_emit (html, signals [INSERTION_FONT_STYLE_CHANGED], 0, html->engine->insertion_font_style); |
---|
4120 | } |
---|
4121 | |
---|
4122 | GtkHTMLParagraphAlignment |
---|
4123 | gtk_html_get_paragraph_alignment (GtkHTML *html) |
---|
4124 | { |
---|
4125 | return paragraph_alignment_to_html (html_engine_get_current_clueflow_alignment (html->engine)); |
---|
4126 | } |
---|
4127 | |
---|
4128 | void |
---|
4129 | gtk_html_set_paragraph_alignment (GtkHTML *html, |
---|
4130 | GtkHTMLParagraphAlignment alignment) |
---|
4131 | { |
---|
4132 | HTMLHAlignType align; |
---|
4133 | |
---|
4134 | g_return_if_fail (html != NULL); |
---|
4135 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4136 | |
---|
4137 | align = paragraph_alignment_to_html (alignment); |
---|
4138 | |
---|
4139 | if (html_engine_set_clueflow_style (html->engine, 0, 0, align, 0, NULL, |
---|
4140 | HTML_ENGINE_SET_CLUEFLOW_ALIGNMENT, HTML_UNDO_UNDO, TRUE)) { |
---|
4141 | html->priv->paragraph_alignment = alignment; |
---|
4142 | g_signal_emit (html, signals [CURRENT_PARAGRAPH_ALIGNMENT_CHANGED], 0, alignment); |
---|
4143 | } |
---|
4144 | } |
---|
4145 | |
---|
4146 | |
---|
4147 | /* Clipboard operations. */ |
---|
4148 | |
---|
4149 | void |
---|
4150 | gtk_html_cut (GtkHTML *html) |
---|
4151 | { |
---|
4152 | g_return_if_fail (html != NULL); |
---|
4153 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4154 | |
---|
4155 | html_engine_cut (html->engine); |
---|
4156 | gtk_selection_owner_set (GTK_WIDGET (html), gdk_atom_intern ("CLIPBOARD", FALSE), gtk_get_current_event_time ()); |
---|
4157 | } |
---|
4158 | |
---|
4159 | void |
---|
4160 | gtk_html_copy (GtkHTML *html) |
---|
4161 | { |
---|
4162 | g_return_if_fail (html != NULL); |
---|
4163 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4164 | |
---|
4165 | html_engine_copy (html->engine); |
---|
4166 | gtk_selection_owner_set (GTK_WIDGET (html), gdk_atom_intern ("CLIPBOARD", FALSE), gtk_get_current_event_time ()); |
---|
4167 | } |
---|
4168 | |
---|
4169 | void |
---|
4170 | gtk_html_paste (GtkHTML *html, gboolean as_cite) |
---|
4171 | { |
---|
4172 | g_return_if_fail (html != NULL); |
---|
4173 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4174 | |
---|
4175 | gtk_html_request_paste (html, gdk_atom_intern ("CLIPBOARD", FALSE), 0, |
---|
4176 | gtk_get_current_event_time (), as_cite); |
---|
4177 | } |
---|
4178 | |
---|
4179 | |
---|
4180 | /* Undo/redo. */ |
---|
4181 | |
---|
4182 | void |
---|
4183 | gtk_html_undo (GtkHTML *html) |
---|
4184 | { |
---|
4185 | g_return_if_fail (html != NULL); |
---|
4186 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4187 | |
---|
4188 | html_engine_undo (html->engine); |
---|
4189 | gtk_html_update_styles (html); |
---|
4190 | } |
---|
4191 | |
---|
4192 | void |
---|
4193 | gtk_html_redo (GtkHTML *html) |
---|
4194 | { |
---|
4195 | g_return_if_fail (html != NULL); |
---|
4196 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
4197 | |
---|
4198 | html_engine_redo (html->engine); |
---|
4199 | gtk_html_update_styles (html); |
---|
4200 | } |
---|
4201 | |
---|
4202 | /* misc utils */ |
---|
4203 | void |
---|
4204 | gtk_html_set_default_content_type (GtkHTML *html, gchar *content_type) |
---|
4205 | { |
---|
4206 | g_free (html->priv->content_type); |
---|
4207 | |
---|
4208 | if (content_type) { |
---|
4209 | html->priv->content_type = g_ascii_strdown (content_type, -1); |
---|
4210 | } else |
---|
4211 | html->priv->content_type = NULL; |
---|
4212 | } |
---|
4213 | |
---|
4214 | gpointer |
---|
4215 | gtk_html_get_object_by_id (GtkHTML *html, const gchar *id) |
---|
4216 | { |
---|
4217 | g_return_val_if_fail (html, NULL); |
---|
4218 | g_return_val_if_fail (id, NULL); |
---|
4219 | g_return_val_if_fail (GTK_IS_HTML (html), NULL); |
---|
4220 | g_return_val_if_fail (html->engine, NULL); |
---|
4221 | |
---|
4222 | return html_engine_get_object_by_id (html->engine, id); |
---|
4223 | } |
---|
4224 | |
---|
4225 | /******************************************* |
---|
4226 | |
---|
4227 | keybindings |
---|
4228 | |
---|
4229 | */ |
---|
4230 | |
---|
4231 | static gint |
---|
4232 | get_line_height (GtkHTML *html) |
---|
4233 | { |
---|
4234 | gint line_offset = 0, w, a, d; |
---|
4235 | |
---|
4236 | if (!html->engine || !html->engine->painter) |
---|
4237 | return 0; |
---|
4238 | |
---|
4239 | html_painter_calc_text_size (html->engine->painter, "a", 1, NULL, NULL, NULL, 0, &line_offset, GTK_HTML_FONT_STYLE_SIZE_3, NULL, &w, &a, &d); |
---|
4240 | |
---|
4241 | return a + d; |
---|
4242 | } |
---|
4243 | |
---|
4244 | static void |
---|
4245 | scroll (GtkHTML *html, |
---|
4246 | GtkOrientation orientation, |
---|
4247 | GtkScrollType scroll_type, |
---|
4248 | gfloat position) |
---|
4249 | { |
---|
4250 | GtkAdjustment *adj; |
---|
4251 | gint line_height; |
---|
4252 | gfloat delta; |
---|
4253 | |
---|
4254 | /* we dont want scroll in editable (move cursor instead) */ |
---|
4255 | if (html_engine_get_editable (html->engine)) |
---|
4256 | return; |
---|
4257 | |
---|
4258 | adj = (orientation == GTK_ORIENTATION_VERTICAL) |
---|
4259 | ? gtk_layout_get_vadjustment (GTK_LAYOUT (html)) : gtk_layout_get_hadjustment (GTK_LAYOUT (html)); |
---|
4260 | |
---|
4261 | |
---|
4262 | line_height = (html->engine && adj->page_increment > (3 * get_line_height (html))) |
---|
4263 | ? get_line_height (html) |
---|
4264 | : 0; |
---|
4265 | |
---|
4266 | switch (scroll_type) { |
---|
4267 | case GTK_SCROLL_STEP_FORWARD: |
---|
4268 | delta = adj->step_increment; |
---|
4269 | break; |
---|
4270 | case GTK_SCROLL_STEP_BACKWARD: |
---|
4271 | delta = -adj->step_increment; |
---|
4272 | break; |
---|
4273 | case GTK_SCROLL_PAGE_FORWARD: |
---|
4274 | delta = adj->page_increment - line_height; |
---|
4275 | break; |
---|
4276 | case GTK_SCROLL_PAGE_BACKWARD: |
---|
4277 | delta = -adj->page_increment + line_height; |
---|
4278 | break; |
---|
4279 | default: |
---|
4280 | g_warning ("invalid scroll parameters: %d %d %f\n", orientation, scroll_type, position); |
---|
4281 | delta = 0.0; |
---|
4282 | return; |
---|
4283 | } |
---|
4284 | |
---|
4285 | gtk_adjustment_set_value (adj, CLAMP (adj->value + delta, adj->lower, MAX (0.0, adj->upper - adj->page_size))); |
---|
4286 | |
---|
4287 | html->binding_handled = TRUE; |
---|
4288 | } |
---|
4289 | |
---|
4290 | static void |
---|
4291 | scroll_by_amount (GtkHTML *html, gint amount) |
---|
4292 | { |
---|
4293 | GtkAdjustment *adj; |
---|
4294 | |
---|
4295 | adj = GTK_LAYOUT (html)->vadjustment; |
---|
4296 | gtk_adjustment_set_value (adj, |
---|
4297 | CLAMP (adj->value + (gfloat) amount, adj->lower, MAX (0.0, adj->upper - adj->page_size))); |
---|
4298 | } |
---|
4299 | |
---|
4300 | static void |
---|
4301 | cursor_move (GtkHTML *html, GtkDirectionType dir_type, GtkHTMLCursorSkipType skip) |
---|
4302 | { |
---|
4303 | gint amount; |
---|
4304 | |
---|
4305 | if (!html->engine->caret_mode && !html_engine_get_editable (html->engine)) |
---|
4306 | return; |
---|
4307 | |
---|
4308 | if (html->engine->selection_mode) { |
---|
4309 | if (!html->engine->mark) |
---|
4310 | html_engine_set_mark (html->engine); |
---|
4311 | } else if (html->engine->shift_selection || html->engine->mark) { |
---|
4312 | html_engine_disable_selection (html->engine); |
---|
4313 | html_engine_edit_selection_updater_schedule (html->engine->selection_updater); |
---|
4314 | html->engine->shift_selection = FALSE; |
---|
4315 | } |
---|
4316 | switch (skip) { |
---|
4317 | case GTK_HTML_CURSOR_SKIP_ONE: |
---|
4318 | switch (dir_type) { |
---|
4319 | case GTK_DIR_LEFT: |
---|
4320 | html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_LEFT, 1); |
---|
4321 | break; |
---|
4322 | case GTK_DIR_RIGHT: |
---|
4323 | html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_RIGHT, 1); |
---|
4324 | break; |
---|
4325 | case GTK_DIR_UP: |
---|
4326 | html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_UP, 1); |
---|
4327 | break; |
---|
4328 | case GTK_DIR_DOWN: |
---|
4329 | html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_DOWN, 1); |
---|
4330 | break; |
---|
4331 | default: |
---|
4332 | g_warning ("invalid cursor_move parameters\n"); |
---|
4333 | } |
---|
4334 | break; |
---|
4335 | case GTK_HTML_CURSOR_SKIP_WORD: |
---|
4336 | switch (dir_type) { |
---|
4337 | case GTK_DIR_UP: |
---|
4338 | case GTK_DIR_LEFT: |
---|
4339 | html_engine_backward_word (html->engine); |
---|
4340 | break; |
---|
4341 | case GTK_DIR_DOWN: |
---|
4342 | case GTK_DIR_RIGHT: |
---|
4343 | html_engine_forward_word (html->engine); |
---|
4344 | break; |
---|
4345 | default: |
---|
4346 | g_warning ("invalid cursor_move parameters\n"); |
---|
4347 | } |
---|
4348 | break; |
---|
4349 | case GTK_HTML_CURSOR_SKIP_PAGE: { |
---|
4350 | gint line_height; |
---|
4351 | |
---|
4352 | line_height = GTK_WIDGET (html)->allocation.height > (3 * get_line_height (html)) |
---|
4353 | ? get_line_height (html) : 0; |
---|
4354 | |
---|
4355 | |
---|
4356 | switch (dir_type) { |
---|
4357 | case GTK_DIR_UP: |
---|
4358 | case GTK_DIR_LEFT: |
---|
4359 | if ((amount = html_engine_scroll_up (html->engine, |
---|
4360 | GTK_WIDGET (html)->allocation.height - line_height)) > 0) |
---|
4361 | scroll_by_amount (html, - amount); |
---|
4362 | break; |
---|
4363 | case GTK_DIR_DOWN: |
---|
4364 | case GTK_DIR_RIGHT: |
---|
4365 | if ((amount = html_engine_scroll_down (html->engine, |
---|
4366 | GTK_WIDGET (html)->allocation.height - line_height)) > 0) |
---|
4367 | scroll_by_amount (html, amount); |
---|
4368 | break; |
---|
4369 | default: |
---|
4370 | g_warning ("invalid cursor_move parameters\n"); |
---|
4371 | } |
---|
4372 | break; |
---|
4373 | } |
---|
4374 | case GTK_HTML_CURSOR_SKIP_ALL: |
---|
4375 | switch (dir_type) { |
---|
4376 | case GTK_DIR_LEFT: |
---|
4377 | html_engine_beginning_of_line (html->engine); |
---|
4378 | break; |
---|
4379 | case GTK_DIR_RIGHT: |
---|
4380 | html_engine_end_of_line (html->engine); |
---|
4381 | break; |
---|
4382 | case GTK_DIR_UP: |
---|
4383 | html_engine_beginning_of_document (html->engine); |
---|
4384 | break; |
---|
4385 | case GTK_DIR_DOWN: |
---|
4386 | html_engine_end_of_document (html->engine); |
---|
4387 | break; |
---|
4388 | default: |
---|
4389 | g_warning ("invalid cursor_move parameters\n"); |
---|
4390 | } |
---|
4391 | break; |
---|
4392 | default: |
---|
4393 | g_warning ("invalid cursor_move parameters\n"); |
---|
4394 | } |
---|
4395 | |
---|
4396 | html->binding_handled = TRUE; |
---|
4397 | html->priv->update_styles = TRUE; |
---|
4398 | gtk_html_edit_make_cursor_visible (html); |
---|
4399 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
4400 | } |
---|
4401 | |
---|
4402 | static gboolean |
---|
4403 | move_selection (GtkHTML *html, GtkHTMLCommandType com_type) |
---|
4404 | { |
---|
4405 | gboolean rv; |
---|
4406 | gint amount; |
---|
4407 | |
---|
4408 | if (!html_engine_get_editable (html->engine) && !html->engine->caret_mode) |
---|
4409 | return FALSE; |
---|
4410 | |
---|
4411 | html->engine->shift_selection = TRUE; |
---|
4412 | if (!html->engine->mark) |
---|
4413 | html_engine_set_mark (html->engine); |
---|
4414 | switch (com_type) { |
---|
4415 | case GTK_HTML_COMMAND_MODIFY_SELECTION_UP: |
---|
4416 | rv = html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_UP, 1) > 0 ? TRUE : FALSE; |
---|
4417 | break; |
---|
4418 | case GTK_HTML_COMMAND_MODIFY_SELECTION_DOWN: |
---|
4419 | rv = html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_DOWN, 1) > 0 ? TRUE : FALSE; |
---|
4420 | break; |
---|
4421 | case GTK_HTML_COMMAND_MODIFY_SELECTION_LEFT: |
---|
4422 | rv = html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_LEFT, 1) > 0 ? TRUE : FALSE; |
---|
4423 | break; |
---|
4424 | case GTK_HTML_COMMAND_MODIFY_SELECTION_RIGHT: |
---|
4425 | rv = html_engine_move_cursor (html->engine, HTML_ENGINE_CURSOR_RIGHT, 1) > 0 ? TRUE : FALSE; |
---|
4426 | break; |
---|
4427 | case GTK_HTML_COMMAND_MODIFY_SELECTION_BOL: |
---|
4428 | rv = html_engine_beginning_of_line (html->engine); |
---|
4429 | break; |
---|
4430 | case GTK_HTML_COMMAND_MODIFY_SELECTION_EOL: |
---|
4431 | rv = html_engine_end_of_line (html->engine); |
---|
4432 | break; |
---|
4433 | case GTK_HTML_COMMAND_MODIFY_SELECTION_BOD: |
---|
4434 | html_engine_beginning_of_document (html->engine); |
---|
4435 | rv = TRUE; |
---|
4436 | break; |
---|
4437 | case GTK_HTML_COMMAND_MODIFY_SELECTION_EOD: |
---|
4438 | html_engine_end_of_document (html->engine); |
---|
4439 | rv = TRUE; |
---|
4440 | break; |
---|
4441 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PREV_WORD: |
---|
4442 | rv = html_engine_backward_word (html->engine); |
---|
4443 | break; |
---|
4444 | case GTK_HTML_COMMAND_MODIFY_SELECTION_NEXT_WORD: |
---|
4445 | rv = html_engine_forward_word (html->engine); |
---|
4446 | break; |
---|
4447 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PAGEUP: |
---|
4448 | if ((amount = html_engine_scroll_up (html->engine, GTK_WIDGET (html)->allocation.height)) > 0) { |
---|
4449 | scroll_by_amount (html, - amount); |
---|
4450 | rv = TRUE; |
---|
4451 | } else |
---|
4452 | rv = FALSE; |
---|
4453 | break; |
---|
4454 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PAGEDOWN: |
---|
4455 | if ((amount = html_engine_scroll_down (html->engine, GTK_WIDGET (html)->allocation.height)) > 0) { |
---|
4456 | scroll_by_amount (html, amount); |
---|
4457 | rv = TRUE; |
---|
4458 | } else |
---|
4459 | rv = FALSE; |
---|
4460 | break; |
---|
4461 | default: |
---|
4462 | g_warning ("invalid move_selection parameters\n"); |
---|
4463 | rv = FALSE; |
---|
4464 | } |
---|
4465 | |
---|
4466 | html->binding_handled = TRUE; |
---|
4467 | html->priv->update_styles = TRUE; |
---|
4468 | |
---|
4469 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
4470 | |
---|
4471 | return rv; |
---|
4472 | } |
---|
4473 | |
---|
4474 | inline static void |
---|
4475 | delete_one (HTMLEngine *e, gboolean forward) |
---|
4476 | { |
---|
4477 | if (e->cursor->object && html_object_is_container (e->cursor->object) |
---|
4478 | && ((forward && !e->cursor->offset) || (!forward && e->cursor->offset))) |
---|
4479 | html_engine_delete_container (e); |
---|
4480 | else |
---|
4481 | html_engine_delete_n (e, 1, forward); |
---|
4482 | } |
---|
4483 | |
---|
4484 | inline static gboolean |
---|
4485 | insert_tab_or_next_cell (GtkHTML *html) |
---|
4486 | { |
---|
4487 | HTMLEngine *e = html->engine; |
---|
4488 | if (!html_engine_next_cell (e, TRUE)) { |
---|
4489 | if (html_clueflow_tabs (HTML_CLUEFLOW (e->cursor->object->parent), e->painter)) |
---|
4490 | html_engine_paste_text (e, "\t", 1); |
---|
4491 | else |
---|
4492 | html_engine_paste_text (e, "\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0", 4); |
---|
4493 | return TRUE; |
---|
4494 | } |
---|
4495 | |
---|
4496 | return TRUE; |
---|
4497 | } |
---|
4498 | |
---|
4499 | inline static void |
---|
4500 | indent_more_or_next_cell (GtkHTML *html) |
---|
4501 | { |
---|
4502 | if (!html_engine_next_cell (html->engine, TRUE)) |
---|
4503 | gtk_html_indent_push_level (html, HTML_LIST_TYPE_BLOCKQUOTE); |
---|
4504 | } |
---|
4505 | |
---|
4506 | static gboolean |
---|
4507 | command (GtkHTML *html, GtkHTMLCommandType com_type) |
---|
4508 | { |
---|
4509 | HTMLEngine *e = html->engine; |
---|
4510 | gboolean rv = TRUE; |
---|
4511 | |
---|
4512 | /* printf ("command %d %s\n", com_type, get_value_nick (com_type)); */ |
---|
4513 | html->binding_handled = TRUE; |
---|
4514 | |
---|
4515 | /* non-editable + editable commands */ |
---|
4516 | switch (com_type) { |
---|
4517 | case GTK_HTML_COMMAND_ZOOM_IN: |
---|
4518 | gtk_html_zoom_in (html); |
---|
4519 | break; |
---|
4520 | case GTK_HTML_COMMAND_ZOOM_OUT: |
---|
4521 | gtk_html_zoom_out (html); |
---|
4522 | break; |
---|
4523 | case GTK_HTML_COMMAND_ZOOM_RESET: |
---|
4524 | gtk_html_zoom_reset (html); |
---|
4525 | break; |
---|
4526 | case GTK_HTML_COMMAND_SEARCH_INCREMENTAL_FORWARD: |
---|
4527 | gtk_html_isearch (html, TRUE); |
---|
4528 | break; |
---|
4529 | case GTK_HTML_COMMAND_SEARCH_INCREMENTAL_BACKWARD: |
---|
4530 | gtk_html_isearch (html, FALSE); |
---|
4531 | break; |
---|
4532 | case GTK_HTML_COMMAND_FOCUS_FORWARD: |
---|
4533 | if (!html_engine_get_editable (e)) |
---|
4534 | html->binding_handled = gtk_widget_child_focus (GTK_WIDGET (html), GTK_DIR_TAB_FORWARD); |
---|
4535 | break; |
---|
4536 | case GTK_HTML_COMMAND_FOCUS_BACKWARD: |
---|
4537 | if (!html_engine_get_editable (e)) |
---|
4538 | html->binding_handled = gtk_widget_child_focus (GTK_WIDGET (html), GTK_DIR_TAB_BACKWARD); |
---|
4539 | break; |
---|
4540 | case GTK_HTML_COMMAND_SCROLL_BOD: |
---|
4541 | if (!html_engine_get_editable (e)) |
---|
4542 | gtk_adjustment_set_value (gtk_layout_get_vadjustment (GTK_LAYOUT (html)), 0); |
---|
4543 | break; |
---|
4544 | case GTK_HTML_COMMAND_SCROLL_EOD: |
---|
4545 | if (!html_engine_get_editable (e)) { |
---|
4546 | GtkAdjustment *vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (html)); |
---|
4547 | gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size); |
---|
4548 | } |
---|
4549 | break; |
---|
4550 | case GTK_HTML_COMMAND_COPY: |
---|
4551 | gtk_html_copy (html); |
---|
4552 | break; |
---|
4553 | |
---|
4554 | case GTK_HTML_COMMAND_MODIFY_SELECTION_UP: |
---|
4555 | case GTK_HTML_COMMAND_MODIFY_SELECTION_DOWN: |
---|
4556 | case GTK_HTML_COMMAND_MODIFY_SELECTION_LEFT: |
---|
4557 | case GTK_HTML_COMMAND_MODIFY_SELECTION_RIGHT: |
---|
4558 | case GTK_HTML_COMMAND_MODIFY_SELECTION_BOL: |
---|
4559 | case GTK_HTML_COMMAND_MODIFY_SELECTION_EOL: |
---|
4560 | case GTK_HTML_COMMAND_MODIFY_SELECTION_BOD: |
---|
4561 | case GTK_HTML_COMMAND_MODIFY_SELECTION_EOD: |
---|
4562 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PAGEUP: |
---|
4563 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PAGEDOWN: |
---|
4564 | case GTK_HTML_COMMAND_MODIFY_SELECTION_PREV_WORD: |
---|
4565 | case GTK_HTML_COMMAND_MODIFY_SELECTION_NEXT_WORD: |
---|
4566 | if (html->engine->caret_mode || html_engine_get_editable(e)) |
---|
4567 | rv = move_selection (html, com_type); |
---|
4568 | break; |
---|
4569 | case GTK_HTML_COMMAND_EDITABLE_ON: |
---|
4570 | gtk_html_set_editable (html, TRUE); |
---|
4571 | break; |
---|
4572 | case GTK_HTML_COMMAND_EDITABLE_OFF: |
---|
4573 | gtk_html_set_editable (html, FALSE); |
---|
4574 | break; |
---|
4575 | |
---|
4576 | default: |
---|
4577 | html->binding_handled = FALSE; |
---|
4578 | } |
---|
4579 | |
---|
4580 | if (!html_engine_get_editable (e) || html->binding_handled) |
---|
4581 | return rv; |
---|
4582 | |
---|
4583 | html->binding_handled = TRUE; |
---|
4584 | html->priv->update_styles = FALSE; |
---|
4585 | |
---|
4586 | /* editable commands only */ |
---|
4587 | switch (com_type) { |
---|
4588 | case GTK_HTML_COMMAND_UNDO: |
---|
4589 | gtk_html_undo (html); |
---|
4590 | break; |
---|
4591 | case GTK_HTML_COMMAND_REDO: |
---|
4592 | gtk_html_redo (html); |
---|
4593 | break; |
---|
4594 | case GTK_HTML_COMMAND_COPY_AND_DISABLE_SELECTION: |
---|
4595 | gtk_html_copy (html); |
---|
4596 | html_engine_disable_selection (e); |
---|
4597 | html_engine_edit_selection_updater_schedule (e->selection_updater); |
---|
4598 | e->selection_mode = FALSE; |
---|
4599 | break; |
---|
4600 | case GTK_HTML_COMMAND_CUT: |
---|
4601 | gtk_html_cut (html); |
---|
4602 | html->priv->update_styles = TRUE; |
---|
4603 | break; |
---|
4604 | case GTK_HTML_COMMAND_CUT_LINE: |
---|
4605 | html_engine_cut_line (e); |
---|
4606 | html->priv->update_styles = TRUE; |
---|
4607 | break; |
---|
4608 | case GTK_HTML_COMMAND_PASTE: |
---|
4609 | gtk_html_paste (html, FALSE); |
---|
4610 | html->priv->update_styles = TRUE; |
---|
4611 | break; |
---|
4612 | case GTK_HTML_COMMAND_INSERT_RULE: |
---|
4613 | html_engine_insert_rule (e, 0, 100, 2, TRUE, HTML_HALIGN_LEFT); |
---|
4614 | break; |
---|
4615 | case GTK_HTML_COMMAND_INSERT_PARAGRAPH: |
---|
4616 | html_engine_delete (e); |
---|
4617 | |
---|
4618 | /* stop inserting links after newlines */ |
---|
4619 | html_engine_set_insertion_link (e, NULL, NULL); |
---|
4620 | |
---|
4621 | html_engine_insert_empty_paragraph (e); |
---|
4622 | html->priv->update_styles = TRUE; |
---|
4623 | break; |
---|
4624 | case GTK_HTML_COMMAND_DELETE: |
---|
4625 | if (e->mark != NULL |
---|
4626 | && e->mark->position != e->cursor->position) |
---|
4627 | html_engine_delete (e); |
---|
4628 | else |
---|
4629 | delete_one (e, TRUE); |
---|
4630 | html->priv->update_styles = TRUE; |
---|
4631 | break; |
---|
4632 | case GTK_HTML_COMMAND_DELETE_BACK: |
---|
4633 | if (html_engine_is_selection_active (e)) |
---|
4634 | html_engine_delete (e); |
---|
4635 | else |
---|
4636 | delete_one (e, FALSE); |
---|
4637 | html->priv->update_styles = TRUE; |
---|
4638 | break; |
---|
4639 | case GTK_HTML_COMMAND_DELETE_BACK_OR_INDENT_DEC: |
---|
4640 | if (html_engine_is_selection_active (e)) |
---|
4641 | html_engine_delete (e); |
---|
4642 | else if (html_engine_cursor_on_bop (e) && html_engine_get_indent (e) > 0 |
---|
4643 | && e->cursor->object->parent && HTML_IS_CLUEFLOW (e->cursor->object->parent) |
---|
4644 | && HTML_CLUEFLOW (e->cursor->object->parent)->style != HTML_CLUEFLOW_STYLE_LIST_ITEM) |
---|
4645 | gtk_html_indent_pop_level (html); |
---|
4646 | else |
---|
4647 | delete_one (e, FALSE); |
---|
4648 | html->priv->update_styles = TRUE; |
---|
4649 | break; |
---|
4650 | case GTK_HTML_COMMAND_DELETE_TABLE: |
---|
4651 | html_engine_delete_table (e); |
---|
4652 | html->priv->update_styles = TRUE; |
---|
4653 | break; |
---|
4654 | case GTK_HTML_COMMAND_DELETE_TABLE_ROW: |
---|
4655 | html_engine_delete_table_row (e); |
---|
4656 | html->priv->update_styles = TRUE; |
---|
4657 | break; |
---|
4658 | case GTK_HTML_COMMAND_DELETE_TABLE_COLUMN: |
---|
4659 | html_engine_delete_table_column (e); |
---|
4660 | html->priv->update_styles = TRUE; |
---|
4661 | break; |
---|
4662 | case GTK_HTML_COMMAND_DELETE_TABLE_CELL_CONTENTS: |
---|
4663 | html_engine_delete_table_cell_contents (e); |
---|
4664 | html->priv->update_styles = TRUE; |
---|
4665 | break; |
---|
4666 | case GTK_HTML_COMMAND_SELECTION_MODE: |
---|
4667 | e->selection_mode = TRUE; |
---|
4668 | break; |
---|
4669 | case GTK_HTML_COMMAND_DISABLE_SELECTION: |
---|
4670 | html_engine_disable_selection (e); |
---|
4671 | html_engine_edit_selection_updater_schedule (e->selection_updater); |
---|
4672 | e->selection_mode = FALSE; |
---|
4673 | break; |
---|
4674 | case GTK_HTML_COMMAND_BOLD_ON: |
---|
4675 | gtk_html_set_font_style (html, GTK_HTML_FONT_STYLE_MAX, GTK_HTML_FONT_STYLE_BOLD); |
---|
4676 | break; |
---|
4677 | case GTK_HTML_COMMAND_BOLD_OFF: |
---|
4678 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_BOLD, 0); |
---|
4679 | break; |
---|
4680 | case GTK_HTML_COMMAND_BOLD_TOGGLE: |
---|
4681 | gtk_html_toggle_font_style (html, GTK_HTML_FONT_STYLE_BOLD); |
---|
4682 | break; |
---|
4683 | case GTK_HTML_COMMAND_ITALIC_ON: |
---|
4684 | gtk_html_set_font_style (html, GTK_HTML_FONT_STYLE_MAX, GTK_HTML_FONT_STYLE_ITALIC); |
---|
4685 | break; |
---|
4686 | case GTK_HTML_COMMAND_ITALIC_OFF: |
---|
4687 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_ITALIC, 0); |
---|
4688 | break; |
---|
4689 | case GTK_HTML_COMMAND_ITALIC_TOGGLE: |
---|
4690 | gtk_html_toggle_font_style (html, GTK_HTML_FONT_STYLE_ITALIC); |
---|
4691 | break; |
---|
4692 | case GTK_HTML_COMMAND_STRIKEOUT_ON: |
---|
4693 | gtk_html_set_font_style (html, GTK_HTML_FONT_STYLE_MAX, GTK_HTML_FONT_STYLE_STRIKEOUT); |
---|
4694 | break; |
---|
4695 | case GTK_HTML_COMMAND_STRIKEOUT_OFF: |
---|
4696 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_STRIKEOUT, 0); |
---|
4697 | break; |
---|
4698 | case GTK_HTML_COMMAND_STRIKEOUT_TOGGLE: |
---|
4699 | gtk_html_toggle_font_style (html, GTK_HTML_FONT_STYLE_STRIKEOUT); |
---|
4700 | break; |
---|
4701 | case GTK_HTML_COMMAND_UNDERLINE_ON: |
---|
4702 | gtk_html_set_font_style (html, GTK_HTML_FONT_STYLE_MAX, GTK_HTML_FONT_STYLE_UNDERLINE); |
---|
4703 | break; |
---|
4704 | case GTK_HTML_COMMAND_UNDERLINE_OFF: |
---|
4705 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_UNDERLINE, 0); |
---|
4706 | break; |
---|
4707 | case GTK_HTML_COMMAND_UNDERLINE_TOGGLE: |
---|
4708 | gtk_html_toggle_font_style (html, GTK_HTML_FONT_STYLE_UNDERLINE); |
---|
4709 | break; |
---|
4710 | case GTK_HTML_COMMAND_SIZE_MINUS_2: |
---|
4711 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_1); |
---|
4712 | break; |
---|
4713 | case GTK_HTML_COMMAND_SIZE_MINUS_1: |
---|
4714 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_2); |
---|
4715 | break; |
---|
4716 | case GTK_HTML_COMMAND_SIZE_PLUS_0: |
---|
4717 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_3); |
---|
4718 | break; |
---|
4719 | case GTK_HTML_COMMAND_SIZE_PLUS_1: |
---|
4720 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_4); |
---|
4721 | break; |
---|
4722 | case GTK_HTML_COMMAND_SIZE_PLUS_2: |
---|
4723 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_5); |
---|
4724 | break; |
---|
4725 | case GTK_HTML_COMMAND_SIZE_PLUS_3: |
---|
4726 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_6); |
---|
4727 | break; |
---|
4728 | case GTK_HTML_COMMAND_SIZE_PLUS_4: |
---|
4729 | gtk_html_set_font_style (html, ~GTK_HTML_FONT_STYLE_SIZE_MASK, GTK_HTML_FONT_STYLE_SIZE_7); |
---|
4730 | break; |
---|
4731 | case GTK_HTML_COMMAND_SIZE_INCREASE: |
---|
4732 | html_engine_font_size_inc_dec (e, TRUE); |
---|
4733 | break; |
---|
4734 | case GTK_HTML_COMMAND_SIZE_DECREASE: |
---|
4735 | html_engine_font_size_inc_dec (e, FALSE); |
---|
4736 | break; |
---|
4737 | case GTK_HTML_COMMAND_ALIGN_LEFT: |
---|
4738 | gtk_html_set_paragraph_alignment (html, GTK_HTML_PARAGRAPH_ALIGNMENT_LEFT); |
---|
4739 | break; |
---|
4740 | case GTK_HTML_COMMAND_ALIGN_CENTER: |
---|
4741 | gtk_html_set_paragraph_alignment (html, GTK_HTML_PARAGRAPH_ALIGNMENT_CENTER); |
---|
4742 | break; |
---|
4743 | case GTK_HTML_COMMAND_ALIGN_RIGHT: |
---|
4744 | gtk_html_set_paragraph_alignment (html, GTK_HTML_PARAGRAPH_ALIGNMENT_RIGHT); |
---|
4745 | break; |
---|
4746 | case GTK_HTML_COMMAND_INDENT_ZERO: |
---|
4747 | gtk_html_set_indent (html, NULL); |
---|
4748 | break; |
---|
4749 | case GTK_HTML_COMMAND_INDENT_INC: |
---|
4750 | gtk_html_indent_push_level (html, HTML_LIST_TYPE_BLOCKQUOTE); |
---|
4751 | break; |
---|
4752 | case GTK_HTML_COMMAND_INDENT_INC_OR_NEXT_CELL: |
---|
4753 | indent_more_or_next_cell (html); |
---|
4754 | break; |
---|
4755 | case GTK_HTML_COMMAND_INSERT_TAB: |
---|
4756 | if (!html_engine_is_selection_active (e) |
---|
4757 | && html_clueflow_tabs (HTML_CLUEFLOW (e->cursor->object->parent), e->painter)) |
---|
4758 | html_engine_insert_text (e, "\t", 1); |
---|
4759 | break; |
---|
4760 | case GTK_HTML_COMMAND_INSERT_TAB_OR_INDENT_MORE: |
---|
4761 | if (!html_engine_is_selection_active (e) |
---|
4762 | && html_clueflow_tabs (HTML_CLUEFLOW (e->cursor->object->parent), e->painter)) |
---|
4763 | html_engine_insert_text (e, "\t", 1); |
---|
4764 | else |
---|
4765 | gtk_html_indent_push_level (html, HTML_LIST_TYPE_BLOCKQUOTE); |
---|
4766 | break; |
---|
4767 | case GTK_HTML_COMMAND_INSERT_TAB_OR_NEXT_CELL: |
---|
4768 | html->binding_handled = insert_tab_or_next_cell (html); |
---|
4769 | break; |
---|
4770 | case GTK_HTML_COMMAND_INDENT_DEC: |
---|
4771 | gtk_html_indent_pop_level (html); |
---|
4772 | break; |
---|
4773 | case GTK_HTML_COMMAND_PREV_CELL: |
---|
4774 | html->binding_handled = html_engine_prev_cell (html->engine); |
---|
4775 | break; |
---|
4776 | case GTK_HTML_COMMAND_INDENT_PARAGRAPH: |
---|
4777 | html_engine_indent_paragraph (e); |
---|
4778 | break; |
---|
4779 | case GTK_HTML_COMMAND_BREAK_AND_FILL_LINE: |
---|
4780 | html_engine_break_and_fill_line (e); |
---|
4781 | break; |
---|
4782 | case GTK_HTML_COMMAND_SPACE_AND_FILL_LINE: |
---|
4783 | html_engine_space_and_fill_line (e); |
---|
4784 | break; |
---|
4785 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_NORMAL: |
---|
4786 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_NORMAL); |
---|
4787 | break; |
---|
4788 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H1: |
---|
4789 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H1); |
---|
4790 | break; |
---|
4791 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H2: |
---|
4792 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H2); |
---|
4793 | break; |
---|
4794 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H3: |
---|
4795 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H3); |
---|
4796 | break; |
---|
4797 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H4: |
---|
4798 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H4); |
---|
4799 | break; |
---|
4800 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H5: |
---|
4801 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H5); |
---|
4802 | break; |
---|
4803 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_H6: |
---|
4804 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_H6); |
---|
4805 | break; |
---|
4806 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_PRE: |
---|
4807 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_PRE); |
---|
4808 | break; |
---|
4809 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_ADDRESS: |
---|
4810 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_ADDRESS); |
---|
4811 | break; |
---|
4812 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_ITEMDOTTED: |
---|
4813 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_ITEMDOTTED); |
---|
4814 | break; |
---|
4815 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_ITEMROMAN: |
---|
4816 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_ITEMROMAN); |
---|
4817 | break; |
---|
4818 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_ITEMDIGIT: |
---|
4819 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_ITEMDIGIT); |
---|
4820 | break; |
---|
4821 | case GTK_HTML_COMMAND_PARAGRAPH_STYLE_ITEMALPHA: |
---|
4822 | gtk_html_set_paragraph_style (html, GTK_HTML_PARAGRAPH_STYLE_ITEMALPHA); |
---|
4823 | break; |
---|
4824 | case GTK_HTML_COMMAND_SELECT_WORD: |
---|
4825 | gtk_html_select_word (html); |
---|
4826 | break; |
---|
4827 | case GTK_HTML_COMMAND_SELECT_LINE: |
---|
4828 | gtk_html_select_line (html); |
---|
4829 | break; |
---|
4830 | case GTK_HTML_COMMAND_SELECT_PARAGRAPH: |
---|
4831 | gtk_html_select_paragraph (html); |
---|
4832 | break; |
---|
4833 | case GTK_HTML_COMMAND_SELECT_PARAGRAPH_EXTENDED: |
---|
4834 | gtk_html_select_paragraph_extended (html); |
---|
4835 | break; |
---|
4836 | case GTK_HTML_COMMAND_SELECT_ALL: |
---|
4837 | gtk_html_select_all (html); |
---|
4838 | break; |
---|
4839 | case GTK_HTML_COMMAND_CURSOR_POSITION_SAVE: |
---|
4840 | html_engine_edit_cursor_position_save (html->engine); |
---|
4841 | break; |
---|
4842 | case GTK_HTML_COMMAND_CURSOR_POSITION_RESTORE: |
---|
4843 | html_engine_edit_cursor_position_restore (html->engine); |
---|
4844 | break; |
---|
4845 | case GTK_HTML_COMMAND_CAPITALIZE_WORD: |
---|
4846 | html_engine_capitalize_word (e); |
---|
4847 | break; |
---|
4848 | case GTK_HTML_COMMAND_UPCASE_WORD: |
---|
4849 | html_engine_upcase_downcase_word (e, TRUE); |
---|
4850 | break; |
---|
4851 | case GTK_HTML_COMMAND_DOWNCASE_WORD: |
---|
4852 | html_engine_upcase_downcase_word (e, FALSE); |
---|
4853 | break; |
---|
4854 | case GTK_HTML_COMMAND_SPELL_SUGGEST: |
---|
4855 | if (html->editor_api && !html_engine_spell_word_is_valid (e)) |
---|
4856 | (*html->editor_api->suggestion_request) (html, html->editor_data); |
---|
4857 | break; |
---|
4858 | case GTK_HTML_COMMAND_SPELL_PERSONAL_DICTIONARY_ADD: |
---|
4859 | case GTK_HTML_COMMAND_SPELL_SESSION_DICTIONARY_ADD: { |
---|
4860 | gchar *word; |
---|
4861 | word = html_engine_get_spell_word (e); |
---|
4862 | |
---|
4863 | if (word && html->editor_api) { |
---|
4864 | if (com_type == GTK_HTML_COMMAND_SPELL_PERSONAL_DICTIONARY_ADD) |
---|
4865 | /* FIXME fire popup menu with more than 1 language enabled */ |
---|
4866 | (*html->editor_api->add_to_personal) (html, word, html_engine_get_language (html->engine), html->editor_data); |
---|
4867 | else |
---|
4868 | (*html->editor_api->add_to_session) (html, word, html->editor_data); |
---|
4869 | g_free (word); |
---|
4870 | html_engine_spell_check (e); |
---|
4871 | gtk_widget_queue_draw (GTK_WIDGET (html)); |
---|
4872 | } |
---|
4873 | break; |
---|
4874 | } |
---|
4875 | case GTK_HTML_COMMAND_CURSOR_FORWARD: |
---|
4876 | rv = html_cursor_forward (html->engine->cursor, html->engine); |
---|
4877 | break; |
---|
4878 | case GTK_HTML_COMMAND_CURSOR_BACKWARD: |
---|
4879 | rv = html_cursor_backward (html->engine->cursor, html->engine); |
---|
4880 | break; |
---|
4881 | case GTK_HTML_COMMAND_INSERT_TABLE_1_1: |
---|
4882 | html_engine_insert_table_1_1 (e); |
---|
4883 | break; |
---|
4884 | case GTK_HTML_COMMAND_TABLE_INSERT_COL_BEFORE: |
---|
4885 | html_engine_insert_table_column (e, FALSE); |
---|
4886 | break; |
---|
4887 | case GTK_HTML_COMMAND_TABLE_INSERT_COL_AFTER: |
---|
4888 | html_engine_insert_table_column (e, TRUE); |
---|
4889 | break; |
---|
4890 | case GTK_HTML_COMMAND_TABLE_DELETE_COL: |
---|
4891 | html_engine_delete_table_column (e); |
---|
4892 | break; |
---|
4893 | case GTK_HTML_COMMAND_TABLE_INSERT_ROW_BEFORE: |
---|
4894 | html_engine_insert_table_row (e, FALSE); |
---|
4895 | break; |
---|
4896 | case GTK_HTML_COMMAND_TABLE_INSERT_ROW_AFTER: |
---|
4897 | html_engine_insert_table_row (e, TRUE); |
---|
4898 | break; |
---|
4899 | case GTK_HTML_COMMAND_TABLE_DELETE_ROW: |
---|
4900 | html_engine_delete_table_row (e); |
---|
4901 | break; |
---|
4902 | case GTK_HTML_COMMAND_TABLE_BORDER_WIDTH_INC: |
---|
4903 | html_engine_table_set_border_width (e, html_engine_get_table (e), 1, TRUE); |
---|
4904 | break; |
---|
4905 | case GTK_HTML_COMMAND_TABLE_BORDER_WIDTH_DEC: |
---|
4906 | html_engine_table_set_border_width (e, html_engine_get_table (e), -1, TRUE); |
---|
4907 | break; |
---|
4908 | case GTK_HTML_COMMAND_TABLE_BORDER_WIDTH_ZERO: |
---|
4909 | html_engine_table_set_border_width (e, html_engine_get_table (e), 0, FALSE); |
---|
4910 | break; |
---|
4911 | case GTK_HTML_COMMAND_TABLE_SPACING_INC: |
---|
4912 | html_engine_table_set_spacing (e, html_engine_get_table (e), 1, TRUE); |
---|
4913 | break; |
---|
4914 | case GTK_HTML_COMMAND_TABLE_SPACING_DEC: |
---|
4915 | html_engine_table_set_spacing (e, html_engine_get_table (e), -1, TRUE); |
---|
4916 | break; |
---|
4917 | case GTK_HTML_COMMAND_TABLE_SPACING_ZERO: |
---|
4918 | html_engine_table_set_spacing (e, html_engine_get_table (e), 0, FALSE); |
---|
4919 | break; |
---|
4920 | case GTK_HTML_COMMAND_TABLE_PADDING_INC: |
---|
4921 | html_engine_table_set_padding (e, html_engine_get_table (e), 1, TRUE); |
---|
4922 | break; |
---|
4923 | case GTK_HTML_COMMAND_TABLE_PADDING_DEC: |
---|
4924 | html_engine_table_set_padding (e, html_engine_get_table (e), -1, TRUE); |
---|
4925 | break; |
---|
4926 | case GTK_HTML_COMMAND_TABLE_PADDING_ZERO: |
---|
4927 | html_engine_table_set_padding (e, html_engine_get_table (e), 0, FALSE); |
---|
4928 | break; |
---|
4929 | case GTK_HTML_COMMAND_TEXT_SET_DEFAULT_COLOR: |
---|
4930 | html_engine_set_color (e, NULL); |
---|
4931 | break; |
---|
4932 | case GTK_HTML_COMMAND_CURSOR_BOD: |
---|
4933 | html_engine_beginning_of_document (e); |
---|
4934 | break; |
---|
4935 | case GTK_HTML_COMMAND_CURSOR_EOD: |
---|
4936 | html_engine_end_of_document (e); |
---|
4937 | break; |
---|
4938 | case GTK_HTML_COMMAND_BLOCK_REDRAW: |
---|
4939 | html_engine_block_redraw (e); |
---|
4940 | break; |
---|
4941 | case GTK_HTML_COMMAND_UNBLOCK_REDRAW: |
---|
4942 | html_engine_unblock_redraw (e); |
---|
4943 | break; |
---|
4944 | case GTK_HTML_COMMAND_GRAB_FOCUS: |
---|
4945 | gtk_widget_grab_focus (GTK_WIDGET (html)); |
---|
4946 | break; |
---|
4947 | case GTK_HTML_COMMAND_KILL_WORD: |
---|
4948 | case GTK_HTML_COMMAND_KILL_WORD_BACKWARD: |
---|
4949 | html_engine_disable_selection (e); |
---|
4950 | html_engine_edit_selection_updater_schedule (e->selection_updater); |
---|
4951 | html_engine_set_mark (html->engine); |
---|
4952 | rv = com_type == GTK_HTML_COMMAND_KILL_WORD |
---|
4953 | ? html_engine_forward_word (html->engine) |
---|
4954 | : html_engine_backward_word (html->engine); |
---|
4955 | html_engine_edit_selection_updater_update_now (e->selection_updater); |
---|
4956 | html_draw_queue_clear (e->draw_queue); |
---|
4957 | if (rv) |
---|
4958 | gtk_html_cut (html); |
---|
4959 | html_engine_disable_selection (e); |
---|
4960 | break; |
---|
4961 | case GTK_HTML_COMMAND_SAVE_DATA_ON: |
---|
4962 | html->engine->save_data = TRUE; |
---|
4963 | break; |
---|
4964 | case GTK_HTML_COMMAND_SAVE_DATA_OFF: |
---|
4965 | html->engine->save_data = FALSE; |
---|
4966 | break; |
---|
4967 | case GTK_HTML_COMMAND_SAVED: |
---|
4968 | html_engine_saved (html->engine); |
---|
4969 | break; |
---|
4970 | case GTK_HTML_COMMAND_IS_SAVED: |
---|
4971 | rv = html_engine_is_saved (html->engine); |
---|
4972 | break; |
---|
4973 | case GTK_HTML_COMMAND_CELL_CSPAN_INC: |
---|
4974 | rv = html_engine_cspan_delta (html->engine, 1); |
---|
4975 | break; |
---|
4976 | case GTK_HTML_COMMAND_CELL_RSPAN_INC: |
---|
4977 | rv = html_engine_rspan_delta (html->engine, 1); |
---|
4978 | break; |
---|
4979 | case GTK_HTML_COMMAND_CELL_CSPAN_DEC: |
---|
4980 | rv = html_engine_cspan_delta (html->engine, -1); |
---|
4981 | break; |
---|
4982 | case GTK_HTML_COMMAND_CELL_RSPAN_DEC: |
---|
4983 | rv = html_engine_rspan_delta (html->engine, -1); |
---|
4984 | break; |
---|
4985 | default: |
---|
4986 | html->binding_handled = FALSE; |
---|
4987 | } |
---|
4988 | |
---|
4989 | if (!html->binding_handled && html->editor_api) |
---|
4990 | html->binding_handled = (* html->editor_api->command) (html, com_type, html->editor_data); |
---|
4991 | |
---|
4992 | return rv; |
---|
4993 | } |
---|
4994 | |
---|
4995 | static void |
---|
4996 | add_bindings (GtkHTMLClass *klass) |
---|
4997 | { |
---|
4998 | GtkBindingSet *binding_set; |
---|
4999 | |
---|
5000 | /* ensure enums are defined */ |
---|
5001 | gtk_html_cursor_skip_get_type (); |
---|
5002 | gtk_html_command_get_type (); |
---|
5003 | |
---|
5004 | binding_set = gtk_binding_set_by_class (klass); |
---|
5005 | |
---|
5006 | /* layout scrolling */ |
---|
5007 | #define BSCROLL(m,key,orient,sc) \ |
---|
5008 | gtk_binding_entry_add_signal (binding_set, GDK_ ## key, m, \ |
---|
5009 | "scroll", 3, \ |
---|
5010 | GTK_TYPE_ORIENTATION, GTK_ORIENTATION_ ## orient, \ |
---|
5011 | GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_ ## sc, \ |
---|
5012 | G_TYPE_FLOAT, 0.0); \ |
---|
5013 | |
---|
5014 | BSCROLL (0, Up, VERTICAL, STEP_BACKWARD); |
---|
5015 | BSCROLL (0, KP_Up, VERTICAL, STEP_BACKWARD); |
---|
5016 | BSCROLL (0, Down, VERTICAL, STEP_FORWARD); |
---|
5017 | BSCROLL (0, KP_Down, VERTICAL, STEP_FORWARD); |
---|
5018 | |
---|
5019 | BSCROLL (0, Left, HORIZONTAL, STEP_BACKWARD); |
---|
5020 | BSCROLL (0, KP_Left, HORIZONTAL, STEP_BACKWARD); |
---|
5021 | BSCROLL (0, Right, HORIZONTAL, STEP_FORWARD); |
---|
5022 | BSCROLL (0, KP_Right, HORIZONTAL, STEP_FORWARD); |
---|
5023 | |
---|
5024 | BSCROLL (0, Page_Up, VERTICAL, PAGE_BACKWARD); |
---|
5025 | BSCROLL (0, KP_Page_Up, VERTICAL, PAGE_BACKWARD); |
---|
5026 | BSCROLL (0, Page_Down, VERTICAL, PAGE_FORWARD); |
---|
5027 | BSCROLL (0, KP_Page_Down, VERTICAL, PAGE_FORWARD); |
---|
5028 | BSCROLL (0, BackSpace, VERTICAL, PAGE_BACKWARD); |
---|
5029 | BSCROLL (0, space, VERTICAL, PAGE_FORWARD); |
---|
5030 | |
---|
5031 | BSCROLL (GDK_SHIFT_MASK, Left, HORIZONTAL, PAGE_BACKWARD); |
---|
5032 | BSCROLL (GDK_SHIFT_MASK, KP_Left, HORIZONTAL, PAGE_BACKWARD); |
---|
5033 | BSCROLL (GDK_SHIFT_MASK, Right, HORIZONTAL, PAGE_FORWARD); |
---|
5034 | BSCROLL (GDK_SHIFT_MASK, KP_Right, HORIZONTAL, PAGE_FORWARD); |
---|
5035 | |
---|
5036 | /* editing */ |
---|
5037 | |
---|
5038 | #define BMOVE(m,key,dir,sk) \ |
---|
5039 | gtk_binding_entry_add_signal (binding_set, GDK_ ## key, m, \ |
---|
5040 | "cursor_move", 2, \ |
---|
5041 | GTK_TYPE_DIRECTION_TYPE, GTK_DIR_ ## dir, \ |
---|
5042 | GTK_TYPE_HTML_CURSOR_SKIP, GTK_HTML_CURSOR_SKIP_ ## sk); |
---|
5043 | |
---|
5044 | BMOVE (0, Left, LEFT, ONE); |
---|
5045 | BMOVE (0, KP_Left, LEFT, ONE); |
---|
5046 | BMOVE (0, Right, RIGHT, ONE); |
---|
5047 | BMOVE (0, KP_Right, RIGHT, ONE); |
---|
5048 | BMOVE (0, Up, UP , ONE); |
---|
5049 | BMOVE (0, KP_Up, UP , ONE); |
---|
5050 | BMOVE (0, Down, DOWN, ONE); |
---|
5051 | BMOVE (0, KP_Down, DOWN, ONE); |
---|
5052 | |
---|
5053 | BMOVE (GDK_CONTROL_MASK, KP_Left, LEFT, WORD); |
---|
5054 | BMOVE (GDK_CONTROL_MASK, Left, LEFT, WORD); |
---|
5055 | BMOVE (GDK_MOD1_MASK, Left, LEFT, WORD); |
---|
5056 | |
---|
5057 | BMOVE (GDK_CONTROL_MASK, KP_Right, RIGHT, WORD); |
---|
5058 | BMOVE (GDK_CONTROL_MASK, Right, RIGHT, WORD); |
---|
5059 | BMOVE (GDK_MOD1_MASK, Right, RIGHT, WORD); |
---|
5060 | |
---|
5061 | BMOVE (0, Page_Up, UP, PAGE); |
---|
5062 | BMOVE (0, KP_Page_Up, UP, PAGE); |
---|
5063 | BMOVE (0, Page_Down, DOWN, PAGE); |
---|
5064 | BMOVE (0, KP_Page_Down, DOWN, PAGE); |
---|
5065 | |
---|
5066 | BMOVE (0, Home, LEFT, ALL); |
---|
5067 | BMOVE (0, KP_Home, LEFT, ALL); |
---|
5068 | BMOVE (0, End, RIGHT, ALL); |
---|
5069 | BMOVE (0, KP_End, RIGHT, ALL); |
---|
5070 | BMOVE (GDK_CONTROL_MASK, Home, UP, ALL); |
---|
5071 | BMOVE (GDK_CONTROL_MASK, KP_Home, UP, ALL); |
---|
5072 | BMOVE (GDK_CONTROL_MASK, End, DOWN, ALL); |
---|
5073 | BMOVE (GDK_CONTROL_MASK, KP_End, DOWN, ALL); |
---|
5074 | |
---|
5075 | #define BCOM(m,key,com) \ |
---|
5076 | gtk_binding_entry_add_signal (binding_set, GDK_ ## key, m, \ |
---|
5077 | "command", 1, \ |
---|
5078 | GTK_TYPE_HTML_COMMAND, GTK_HTML_COMMAND_ ## com); |
---|
5079 | BCOM (0, Home, SCROLL_BOD); |
---|
5080 | BCOM (0, KP_Home, SCROLL_BOD); |
---|
5081 | BCOM (0, End, SCROLL_EOD); |
---|
5082 | BCOM (0, KP_End, SCROLL_EOD); |
---|
5083 | |
---|
5084 | BCOM (GDK_CONTROL_MASK, c, COPY); |
---|
5085 | |
---|
5086 | BCOM (0, Return, INSERT_PARAGRAPH); |
---|
5087 | BCOM (0, KP_Enter, INSERT_PARAGRAPH); |
---|
5088 | BCOM (0, BackSpace, DELETE_BACK_OR_INDENT_DEC); |
---|
5089 | BCOM (GDK_SHIFT_MASK, BackSpace, DELETE_BACK_OR_INDENT_DEC); |
---|
5090 | BCOM (0, Delete, DELETE); |
---|
5091 | BCOM (0, KP_Delete, DELETE); |
---|
5092 | |
---|
5093 | BCOM (GDK_CONTROL_MASK | GDK_SHIFT_MASK, plus, ZOOM_IN); |
---|
5094 | BCOM (GDK_CONTROL_MASK, plus, ZOOM_IN); |
---|
5095 | BCOM (GDK_CONTROL_MASK, equal, ZOOM_IN); |
---|
5096 | BCOM (GDK_CONTROL_MASK, KP_Add, ZOOM_IN); |
---|
5097 | BCOM (GDK_CONTROL_MASK, minus, ZOOM_OUT); |
---|
5098 | BCOM (GDK_CONTROL_MASK, KP_Subtract, ZOOM_OUT); |
---|
5099 | BCOM (GDK_CONTROL_MASK, 8, ZOOM_IN); |
---|
5100 | BCOM (GDK_CONTROL_MASK, 9, ZOOM_RESET); |
---|
5101 | BCOM (GDK_CONTROL_MASK, 0, ZOOM_OUT); |
---|
5102 | BCOM (GDK_CONTROL_MASK, KP_Multiply, ZOOM_RESET); |
---|
5103 | |
---|
5104 | /* selection */ |
---|
5105 | BCOM (GDK_SHIFT_MASK, Up, MODIFY_SELECTION_UP); |
---|
5106 | BCOM (GDK_SHIFT_MASK, Down, MODIFY_SELECTION_DOWN); |
---|
5107 | BCOM (GDK_SHIFT_MASK, Left, MODIFY_SELECTION_LEFT); |
---|
5108 | BCOM (GDK_SHIFT_MASK, Right, MODIFY_SELECTION_RIGHT); |
---|
5109 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, Left, MODIFY_SELECTION_PREV_WORD); |
---|
5110 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, Right, MODIFY_SELECTION_NEXT_WORD); |
---|
5111 | BCOM (GDK_SHIFT_MASK, Home, MODIFY_SELECTION_BOL); |
---|
5112 | BCOM (GDK_SHIFT_MASK, KP_Home, MODIFY_SELECTION_BOL); |
---|
5113 | BCOM (GDK_SHIFT_MASK, End, MODIFY_SELECTION_EOL); |
---|
5114 | BCOM (GDK_SHIFT_MASK, KP_End, MODIFY_SELECTION_EOL); |
---|
5115 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, Home, MODIFY_SELECTION_BOD); |
---|
5116 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, KP_Home, MODIFY_SELECTION_BOD); |
---|
5117 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, End, MODIFY_SELECTION_EOD); |
---|
5118 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, KP_End, MODIFY_SELECTION_EOD); |
---|
5119 | BCOM (GDK_SHIFT_MASK, Page_Up, MODIFY_SELECTION_PAGEUP); |
---|
5120 | BCOM (GDK_SHIFT_MASK, Page_Down, MODIFY_SELECTION_PAGEDOWN); |
---|
5121 | BCOM (GDK_SHIFT_MASK, KP_Page_Up, MODIFY_SELECTION_PAGEUP); |
---|
5122 | BCOM (GDK_SHIFT_MASK, KP_Page_Down, MODIFY_SELECTION_PAGEDOWN); |
---|
5123 | BCOM (GDK_CONTROL_MASK, a, SELECT_ALL); |
---|
5124 | BCOM (GDK_CONTROL_MASK, p, SELECT_PARAGRAPH); |
---|
5125 | |
---|
5126 | /* copy, cut, paste, delete */ |
---|
5127 | BCOM (GDK_CONTROL_MASK, c, COPY); |
---|
5128 | BCOM (GDK_CONTROL_MASK, Insert, COPY); |
---|
5129 | BCOM (GDK_CONTROL_MASK, KP_Insert, COPY); |
---|
5130 | BCOM (GDK_CONTROL_MASK, x, CUT); |
---|
5131 | BCOM (GDK_SHIFT_MASK, Delete, CUT); |
---|
5132 | BCOM (GDK_SHIFT_MASK, KP_Delete, CUT); |
---|
5133 | BCOM (GDK_CONTROL_MASK, v, PASTE); |
---|
5134 | BCOM (GDK_SHIFT_MASK, Insert, PASTE); |
---|
5135 | BCOM (GDK_SHIFT_MASK, KP_Insert, PASTE); |
---|
5136 | BCOM (GDK_CONTROL_MASK, Delete, KILL_WORD); |
---|
5137 | BCOM (GDK_CONTROL_MASK, BackSpace, KILL_WORD_BACKWARD); |
---|
5138 | |
---|
5139 | /* font style */ |
---|
5140 | BCOM (GDK_CONTROL_MASK, b, BOLD_TOGGLE); |
---|
5141 | BCOM (GDK_CONTROL_MASK, i, ITALIC_TOGGLE); |
---|
5142 | BCOM (GDK_CONTROL_MASK, u, UNDERLINE_TOGGLE); |
---|
5143 | BCOM (GDK_CONTROL_MASK, o, TEXT_COLOR_APPLY); |
---|
5144 | BCOM (GDK_MOD1_MASK, 1, SIZE_MINUS_2); |
---|
5145 | BCOM (GDK_MOD1_MASK, 2, SIZE_MINUS_1); |
---|
5146 | BCOM (GDK_MOD1_MASK, 3, SIZE_PLUS_0); |
---|
5147 | BCOM (GDK_MOD1_MASK, 4, SIZE_PLUS_1); |
---|
5148 | BCOM (GDK_MOD1_MASK, 5, SIZE_PLUS_2); |
---|
5149 | BCOM (GDK_MOD1_MASK, 6, SIZE_PLUS_3); |
---|
5150 | BCOM (GDK_MOD1_MASK, 7, SIZE_PLUS_4); |
---|
5151 | BCOM (GDK_MOD1_MASK, 8, SIZE_INCREASE); |
---|
5152 | BCOM (GDK_MOD1_MASK, 9, SIZE_DECREASE); |
---|
5153 | |
---|
5154 | /* undo/redo */ |
---|
5155 | BCOM (GDK_CONTROL_MASK, z, UNDO); |
---|
5156 | BCOM (GDK_CONTROL_MASK, r, REDO); |
---|
5157 | |
---|
5158 | /* paragraph style */ |
---|
5159 | BCOM (GDK_CONTROL_MASK | GDK_MOD1_MASK, l, ALIGN_LEFT); |
---|
5160 | BCOM (GDK_CONTROL_MASK | GDK_MOD1_MASK, r, ALIGN_RIGHT); |
---|
5161 | BCOM (GDK_CONTROL_MASK | GDK_MOD1_MASK, c, ALIGN_CENTER); |
---|
5162 | |
---|
5163 | /* tabs */ |
---|
5164 | BCOM (0, Tab, INSERT_TAB_OR_NEXT_CELL); |
---|
5165 | BCOM (GDK_SHIFT_MASK, Tab, PREV_CELL); |
---|
5166 | |
---|
5167 | /* spell checking */ |
---|
5168 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK, s, SPELL_SUGGEST); |
---|
5169 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK, p, SPELL_PERSONAL_DICTIONARY_ADD); |
---|
5170 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK, n, SPELL_SESSION_DICTIONARY_ADD); |
---|
5171 | |
---|
5172 | /* popup menu, properties dialog */ |
---|
5173 | BCOM (GDK_MOD1_MASK, space, POPUP_MENU); |
---|
5174 | BCOM (GDK_MOD1_MASK, Return, PROPERTIES_DIALOG); |
---|
5175 | BCOM (GDK_MOD1_MASK, KP_Enter, PROPERTIES_DIALOG); |
---|
5176 | |
---|
5177 | /* tables */ |
---|
5178 | BCOM (GDK_CONTROL_MASK | GDK_SHIFT_MASK, t, INSERT_TABLE_1_1); |
---|
5179 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, c, TABLE_INSERT_COL_AFTER); |
---|
5180 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, r, TABLE_INSERT_ROW_AFTER); |
---|
5181 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, s, TABLE_SPACING_INC); |
---|
5182 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, p, TABLE_PADDING_INC); |
---|
5183 | BCOM (GDK_SHIFT_MASK | GDK_CONTROL_MASK, b, TABLE_BORDER_WIDTH_INC); |
---|
5184 | BCOM (GDK_MOD1_MASK | GDK_CONTROL_MASK, c, TABLE_INSERT_COL_BEFORE); |
---|
5185 | BCOM (GDK_MOD1_MASK | GDK_CONTROL_MASK, r, TABLE_INSERT_ROW_BEFORE); |
---|
5186 | BCOM (GDK_MOD1_MASK | GDK_CONTROL_MASK, s, TABLE_SPACING_DEC); |
---|
5187 | BCOM (GDK_MOD1_MASK | GDK_CONTROL_MASK, p, TABLE_PADDING_DEC); |
---|
5188 | BCOM (GDK_MOD1_MASK | GDK_CONTROL_MASK, b, TABLE_BORDER_WIDTH_DEC); |
---|
5189 | BCOM (GDK_SHIFT_MASK | GDK_MOD1_MASK, c, TABLE_DELETE_COL); |
---|
5190 | BCOM (GDK_SHIFT_MASK | GDK_MOD1_MASK, r, TABLE_DELETE_ROW); |
---|
5191 | BCOM (GDK_SHIFT_MASK | GDK_MOD1_MASK, s, TABLE_SPACING_ZERO); |
---|
5192 | BCOM (GDK_SHIFT_MASK | GDK_MOD1_MASK, p, TABLE_PADDING_ZERO); |
---|
5193 | BCOM (GDK_SHIFT_MASK | GDK_MOD1_MASK, b, TABLE_BORDER_WIDTH_ZERO); |
---|
5194 | } |
---|
5195 | |
---|
5196 | gint |
---|
5197 | gtk_html_set_iframe_parent (GtkHTML *html, GtkWidget *parent, HTMLObject *frame) |
---|
5198 | { |
---|
5199 | GtkWidget *top_level; |
---|
5200 | gint depth = 0; |
---|
5201 | g_assert (GTK_IS_HTML (parent)); |
---|
5202 | |
---|
5203 | gtk_html_set_animate (html, gtk_html_get_animate (GTK_HTML (parent))); |
---|
5204 | |
---|
5205 | html->iframe_parent = parent; |
---|
5206 | html->frame = frame; |
---|
5207 | |
---|
5208 | top_level = GTK_WIDGET (gtk_html_get_top_html (html)); |
---|
5209 | if (html->engine && html->engine->painter) { |
---|
5210 | html_painter_set_widget (html->engine->painter, top_level); |
---|
5211 | gtk_html_set_fonts (html, html->engine->painter); |
---|
5212 | } |
---|
5213 | g_signal_emit (top_level, signals [IFRAME_CREATED], 0, html); |
---|
5214 | |
---|
5215 | while (html->iframe_parent) { |
---|
5216 | depth++; |
---|
5217 | html = GTK_HTML (html->iframe_parent); |
---|
5218 | } |
---|
5219 | |
---|
5220 | return depth; |
---|
5221 | } |
---|
5222 | |
---|
5223 | void |
---|
5224 | gtk_html_select_word (GtkHTML *html) |
---|
5225 | { |
---|
5226 | HTMLEngine *e; |
---|
5227 | |
---|
5228 | if (!html->allow_selection) |
---|
5229 | return; |
---|
5230 | |
---|
5231 | e = html->engine; |
---|
5232 | if (html_engine_get_editable (e)) |
---|
5233 | html_engine_select_word_editable (e); |
---|
5234 | else |
---|
5235 | html_engine_select_word (e); |
---|
5236 | |
---|
5237 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
5238 | } |
---|
5239 | |
---|
5240 | void |
---|
5241 | gtk_html_select_line (GtkHTML *html) |
---|
5242 | { |
---|
5243 | HTMLEngine *e; |
---|
5244 | |
---|
5245 | if (!html->allow_selection) |
---|
5246 | return; |
---|
5247 | |
---|
5248 | e = html->engine; |
---|
5249 | if (html_engine_get_editable (e)) |
---|
5250 | html_engine_select_line_editable (e); |
---|
5251 | else |
---|
5252 | html_engine_select_line (e); |
---|
5253 | |
---|
5254 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
5255 | } |
---|
5256 | |
---|
5257 | void |
---|
5258 | gtk_html_select_paragraph (GtkHTML *html) |
---|
5259 | { |
---|
5260 | HTMLEngine *e; |
---|
5261 | |
---|
5262 | if (!html->allow_selection) |
---|
5263 | return; |
---|
5264 | |
---|
5265 | e = html->engine; |
---|
5266 | if (html_engine_get_editable (e)) |
---|
5267 | html_engine_select_paragraph_editable (e); |
---|
5268 | /* FIXME: does anybody need this? if so bother me. rodo |
---|
5269 | else |
---|
5270 | html_engine_select_paragraph (e); */ |
---|
5271 | |
---|
5272 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
5273 | } |
---|
5274 | |
---|
5275 | void |
---|
5276 | gtk_html_select_paragraph_extended (GtkHTML *html) |
---|
5277 | { |
---|
5278 | HTMLEngine *e; |
---|
5279 | |
---|
5280 | if (!html->allow_selection) |
---|
5281 | return; |
---|
5282 | |
---|
5283 | e = html->engine; |
---|
5284 | if (html_engine_get_editable (e)) |
---|
5285 | html_engine_select_paragraph_extended (e); |
---|
5286 | /* FIXME: does anybody need this? if so bother me. rodo |
---|
5287 | else |
---|
5288 | html_engine_select_paragraph (e); */ |
---|
5289 | |
---|
5290 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
5291 | } |
---|
5292 | |
---|
5293 | void |
---|
5294 | gtk_html_select_all (GtkHTML *html) |
---|
5295 | { |
---|
5296 | HTMLEngine *e; |
---|
5297 | |
---|
5298 | if (!html->allow_selection) |
---|
5299 | return; |
---|
5300 | |
---|
5301 | e = html->engine; |
---|
5302 | |
---|
5303 | if (html_engine_get_editable (e)) |
---|
5304 | html_engine_select_all_editable (e); |
---|
5305 | else { |
---|
5306 | html_engine_select_all (e); |
---|
5307 | } |
---|
5308 | |
---|
5309 | html_engine_update_selection_active_state (html->engine, html->priv->event_time); |
---|
5310 | } |
---|
5311 | |
---|
5312 | void |
---|
5313 | gtk_html_api_set_language (GtkHTML *html) |
---|
5314 | { |
---|
5315 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5316 | |
---|
5317 | if (html->editor_api) { |
---|
5318 | html->editor_api->set_language (html, html_engine_get_language (html->engine), html->editor_data); |
---|
5319 | html_engine_spell_check (html->engine); |
---|
5320 | } |
---|
5321 | } |
---|
5322 | |
---|
5323 | void |
---|
5324 | gtk_html_set_editor_api (GtkHTML *html, GtkHTMLEditorAPI *api, gpointer data) |
---|
5325 | { |
---|
5326 | html->editor_api = api; |
---|
5327 | html->editor_data = data; |
---|
5328 | |
---|
5329 | gtk_html_api_set_language (html); |
---|
5330 | } |
---|
5331 | |
---|
5332 | static gchar * |
---|
5333 | get_value_nick (GtkHTMLCommandType com_type) |
---|
5334 | { |
---|
5335 | GEnumValue *val; |
---|
5336 | GEnumClass *enum_class; |
---|
5337 | |
---|
5338 | enum_class = g_type_class_ref (GTK_TYPE_HTML_COMMAND); |
---|
5339 | val = g_enum_get_value (enum_class, com_type); |
---|
5340 | g_type_class_unref (enum_class); |
---|
5341 | if (val) |
---|
5342 | return val->value_nick; |
---|
5343 | |
---|
5344 | g_warning ("Invalid GTK_TYPE_HTML_COMMAND enum value %d\n", com_type); |
---|
5345 | |
---|
5346 | return NULL; |
---|
5347 | } |
---|
5348 | |
---|
5349 | void |
---|
5350 | gtk_html_editor_event_command (GtkHTML *html, GtkHTMLCommandType com_type, gboolean before) |
---|
5351 | { |
---|
5352 | GValue arg; |
---|
5353 | |
---|
5354 | memset (&arg, 0, sizeof (GValue)); |
---|
5355 | g_value_init (&arg, G_TYPE_STRING); |
---|
5356 | g_value_set_string (&arg, get_value_nick (com_type)); |
---|
5357 | |
---|
5358 | /* printf ("sending %s\n", GTK_VALUE_STRING (*args [0])); */ |
---|
5359 | gtk_html_editor_event (html, before ? GTK_HTML_EDITOR_EVENT_COMMAND_BEFORE : GTK_HTML_EDITOR_EVENT_COMMAND_AFTER, |
---|
5360 | &arg); |
---|
5361 | |
---|
5362 | g_value_unset (&arg); |
---|
5363 | } |
---|
5364 | |
---|
5365 | void |
---|
5366 | gtk_html_editor_event (GtkHTML *html, GtkHTMLEditorEventType event, GValue *args) |
---|
5367 | { |
---|
5368 | GValue *retval = NULL; |
---|
5369 | |
---|
5370 | if (html->editor_api && !html->engine->block_events) |
---|
5371 | retval = (*html->editor_api->event) (html, event, args, html->editor_data); |
---|
5372 | |
---|
5373 | if (retval) { |
---|
5374 | g_value_unset (retval); |
---|
5375 | g_free (retval); |
---|
5376 | } |
---|
5377 | } |
---|
5378 | |
---|
5379 | gboolean |
---|
5380 | gtk_html_command (GtkHTML *html, const gchar *command_name) |
---|
5381 | { |
---|
5382 | GEnumClass *class; |
---|
5383 | GEnumValue *val; |
---|
5384 | |
---|
5385 | class = G_ENUM_CLASS (g_type_class_ref (GTK_TYPE_HTML_COMMAND)); |
---|
5386 | val = g_enum_get_value_by_nick (class, command_name); |
---|
5387 | g_type_class_unref (class); |
---|
5388 | if (val) { |
---|
5389 | if (command (html, val->value)) { |
---|
5390 | if (html->priv->update_styles) |
---|
5391 | gtk_html_update_styles (html); |
---|
5392 | return TRUE; |
---|
5393 | } |
---|
5394 | } |
---|
5395 | |
---|
5396 | return FALSE; |
---|
5397 | } |
---|
5398 | |
---|
5399 | gboolean |
---|
5400 | gtk_html_edit_make_cursor_visible (GtkHTML *html) |
---|
5401 | { |
---|
5402 | gboolean rv = FALSE; |
---|
5403 | |
---|
5404 | g_return_val_if_fail (GTK_IS_HTML (html), rv); |
---|
5405 | |
---|
5406 | html_engine_hide_cursor (html->engine); |
---|
5407 | if (html_engine_make_cursor_visible (html->engine)) { |
---|
5408 | gtk_adjustment_set_value (GTK_LAYOUT (html)->hadjustment, (gfloat) html->engine->x_offset); |
---|
5409 | gtk_adjustment_set_value (GTK_LAYOUT (html)->vadjustment, (gfloat) html->engine->y_offset); |
---|
5410 | rv = TRUE; |
---|
5411 | } |
---|
5412 | html_engine_show_cursor (html->engine); |
---|
5413 | |
---|
5414 | return rv; |
---|
5415 | } |
---|
5416 | |
---|
5417 | gboolean |
---|
5418 | gtk_html_build_with_gconf () |
---|
5419 | { |
---|
5420 | return TRUE; |
---|
5421 | } |
---|
5422 | |
---|
5423 | static void |
---|
5424 | reparent_embedded (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
5425 | { |
---|
5426 | if (html_object_is_embedded (o)) { |
---|
5427 | HTMLEmbedded *eo = HTML_EMBEDDED (o); |
---|
5428 | |
---|
5429 | if (eo->widget && eo->widget->parent && GTK_IS_HTML (eo->widget->parent) && |
---|
5430 | GTK_HTML (eo->widget->parent)->iframe_parent == NULL) { |
---|
5431 | g_object_ref (eo->widget); |
---|
5432 | gtk_container_remove (GTK_CONTAINER (eo->widget->parent), eo->widget); |
---|
5433 | GTK_OBJECT_FLAGS (eo->widget) = GTK_FLOATING; |
---|
5434 | } |
---|
5435 | eo->parent = data; |
---|
5436 | } |
---|
5437 | |
---|
5438 | if (HTML_IS_IFRAME (o) && GTK_HTML (HTML_IFRAME (o)->html)->iframe_parent && |
---|
5439 | GTK_HTML (GTK_HTML (HTML_IFRAME (o)->html)->iframe_parent)->iframe_parent == NULL) |
---|
5440 | gtk_html_set_iframe_parent (GTK_HTML (HTML_IFRAME (o)->html), data, o); |
---|
5441 | |
---|
5442 | if (HTML_IS_FRAME (o) && GTK_HTML (HTML_FRAME (o)->html)->iframe_parent && |
---|
5443 | GTK_HTML (GTK_HTML (HTML_FRAME (o)->html)->iframe_parent)->iframe_parent == NULL) |
---|
5444 | gtk_html_set_iframe_parent (GTK_HTML (HTML_FRAME (o)->html), data, o); |
---|
5445 | |
---|
5446 | } |
---|
5447 | |
---|
5448 | static void |
---|
5449 | gtk_html_insert_html_generic (GtkHTML *html, GtkHTML *tmp, const gchar *html_src, gboolean obj_only) |
---|
5450 | { |
---|
5451 | GtkWidget *window, *sw; |
---|
5452 | HTMLObject *o; |
---|
5453 | |
---|
5454 | html_engine_freeze (html->engine); |
---|
5455 | html_engine_delete (html->engine); |
---|
5456 | if (!tmp) |
---|
5457 | tmp = GTK_HTML (gtk_html_new_from_string (html_src, -1)); |
---|
5458 | window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
---|
5459 | sw = gtk_scrolled_window_new (NULL, NULL); |
---|
5460 | gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (sw)); |
---|
5461 | gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (tmp)); |
---|
5462 | gtk_widget_realize (GTK_WIDGET (tmp)); |
---|
5463 | html_image_factory_move_images (html->engine->image_factory, tmp->engine->image_factory); |
---|
5464 | |
---|
5465 | /* copy the forms */ |
---|
5466 | g_list_foreach (tmp->engine->formList, (GFunc)html_form_set_engine, html->engine); |
---|
5467 | |
---|
5468 | /* move top level iframes and embedded widgets from tmp to html */ |
---|
5469 | html_object_forall (tmp->engine->clue, html->engine, reparent_embedded, html); |
---|
5470 | |
---|
5471 | if (tmp->engine->formList && html->engine->formList) { |
---|
5472 | GList *form_last; |
---|
5473 | |
---|
5474 | form_last = g_list_last (html->engine->formList); |
---|
5475 | tmp->engine->formList->prev = form_last; |
---|
5476 | form_last->next = tmp->engine->formList; |
---|
5477 | } else if (tmp->engine->formList) { |
---|
5478 | html->engine->formList = tmp->engine->formList; |
---|
5479 | } |
---|
5480 | tmp->engine->formList = NULL; |
---|
5481 | |
---|
5482 | if (obj_only) { |
---|
5483 | HTMLObject *next; |
---|
5484 | g_return_if_fail (tmp->engine->clue && HTML_CLUE (tmp->engine->clue)->head |
---|
5485 | && HTML_CLUE (HTML_CLUE (tmp->engine->clue)->head)->head); |
---|
5486 | |
---|
5487 | html_undo_level_begin (html->engine->undo, "Append HTML", "Remove appended HTML"); |
---|
5488 | o = HTML_CLUE (tmp->engine->clue)->head; |
---|
5489 | for (; o; o = next) { |
---|
5490 | next = o->next; |
---|
5491 | html_object_remove_child (o->parent, o); |
---|
5492 | html_engine_append_flow (html->engine, o, html_object_get_recursive_length (o)); |
---|
5493 | } |
---|
5494 | html_undo_level_end (html->engine->undo); |
---|
5495 | } else { |
---|
5496 | g_return_if_fail (tmp->engine->clue); |
---|
5497 | |
---|
5498 | o = tmp->engine->clue; |
---|
5499 | tmp->engine->clue = NULL; |
---|
5500 | html_engine_insert_object (html->engine, o, |
---|
5501 | html_object_get_recursive_length (o), |
---|
5502 | html_object_get_insert_level (o)); |
---|
5503 | } |
---|
5504 | gtk_widget_destroy (window); |
---|
5505 | html_engine_thaw (html->engine); |
---|
5506 | } |
---|
5507 | |
---|
5508 | void |
---|
5509 | gtk_html_insert_html (GtkHTML *html, const gchar *html_src) |
---|
5510 | { |
---|
5511 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5512 | |
---|
5513 | gtk_html_insert_html_generic (html, NULL, html_src, FALSE); |
---|
5514 | } |
---|
5515 | |
---|
5516 | void |
---|
5517 | gtk_html_insert_gtk_html (GtkHTML *html, GtkHTML *to_be_destroyed) |
---|
5518 | { |
---|
5519 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5520 | |
---|
5521 | gtk_html_insert_html_generic (html, to_be_destroyed, NULL, FALSE); |
---|
5522 | } |
---|
5523 | |
---|
5524 | void |
---|
5525 | gtk_html_append_html (GtkHTML *html, const gchar *html_src) |
---|
5526 | { |
---|
5527 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5528 | |
---|
5529 | gtk_html_insert_html_generic (html, NULL, html_src, TRUE); |
---|
5530 | } |
---|
5531 | |
---|
5532 | static void |
---|
5533 | set_magnification (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
5534 | { |
---|
5535 | if (HTML_IS_FRAME (o)) { |
---|
5536 | html_font_manager_set_magnification (>K_HTML (HTML_FRAME (o)->html)->engine->painter->font_manager, |
---|
5537 | *(gdouble *) data); |
---|
5538 | } else if (HTML_IS_IFRAME (o)) { |
---|
5539 | html_font_manager_set_magnification (>K_HTML (HTML_IFRAME (o)->html)->engine->painter->font_manager, |
---|
5540 | *(gdouble *) data); |
---|
5541 | } else if (HTML_IS_TEXT (o)) |
---|
5542 | html_text_calc_font_size (HTML_TEXT (o), e); |
---|
5543 | } |
---|
5544 | |
---|
5545 | void |
---|
5546 | gtk_html_set_magnification (GtkHTML *html, gdouble magnification) |
---|
5547 | { |
---|
5548 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5549 | |
---|
5550 | if (magnification > 0.05 && magnification < 20.0 |
---|
5551 | && magnification * html->engine->painter->font_manager.var_size >= 4*PANGO_SCALE |
---|
5552 | && magnification * html->engine->painter->font_manager.fix_size >= 4*PANGO_SCALE) { |
---|
5553 | html_font_manager_set_magnification (&html->engine->painter->font_manager, magnification); |
---|
5554 | if (html->engine->clue) { |
---|
5555 | html_object_forall (html->engine->clue, html->engine, |
---|
5556 | set_magnification, &magnification); |
---|
5557 | html_object_change_set_down (html->engine->clue, HTML_CHANGE_ALL); |
---|
5558 | } |
---|
5559 | |
---|
5560 | html_engine_schedule_update (html->engine); |
---|
5561 | } |
---|
5562 | } |
---|
5563 | |
---|
5564 | #define MAG_STEP 1.1 |
---|
5565 | |
---|
5566 | void |
---|
5567 | gtk_html_zoom_in (GtkHTML *html) |
---|
5568 | { |
---|
5569 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5570 | |
---|
5571 | gtk_html_set_magnification (html, html->engine->painter->font_manager.magnification * MAG_STEP); |
---|
5572 | } |
---|
5573 | |
---|
5574 | void |
---|
5575 | gtk_html_zoom_out (GtkHTML *html) |
---|
5576 | { |
---|
5577 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5578 | g_return_if_fail (HTML_IS_ENGINE (html->engine)); |
---|
5579 | |
---|
5580 | gtk_html_set_magnification (html, html->engine->painter->font_manager.magnification * (1.0/MAG_STEP)); |
---|
5581 | } |
---|
5582 | |
---|
5583 | void |
---|
5584 | gtk_html_zoom_reset (GtkHTML *html) |
---|
5585 | { |
---|
5586 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5587 | |
---|
5588 | gtk_html_set_magnification (html, 1.0); |
---|
5589 | } |
---|
5590 | |
---|
5591 | void |
---|
5592 | gtk_html_set_allow_frameset (GtkHTML *html, gboolean allow) |
---|
5593 | { |
---|
5594 | g_return_if_fail (GTK_IS_HTML (html)); |
---|
5595 | g_return_if_fail (HTML_IS_ENGINE (html->engine)); |
---|
5596 | |
---|
5597 | html->engine->allow_frameset = allow; |
---|
5598 | } |
---|
5599 | |
---|
5600 | gboolean |
---|
5601 | gtk_html_get_allow_frameset (GtkHTML *html) |
---|
5602 | { |
---|
5603 | g_return_val_if_fail (GTK_IS_HTML (html), FALSE); |
---|
5604 | g_return_val_if_fail (HTML_IS_ENGINE (html->engine), FALSE); |
---|
5605 | |
---|
5606 | return html->engine->allow_frameset; |
---|
5607 | } |
---|
5608 | |
---|
5609 | void |
---|
5610 | gtk_html_print_set_master (GtkHTML *html, GnomePrintJob *print_master) |
---|
5611 | { |
---|
5612 | html->priv->print_master = print_master; |
---|
5613 | } |
---|
5614 | |
---|
5615 | void |
---|
5616 | gtk_html_images_ref (GtkHTML *html) |
---|
5617 | { |
---|
5618 | html_image_factory_ref_all_images (HTML_IMAGE_FACTORY (html->engine->image_factory)); |
---|
5619 | } |
---|
5620 | |
---|
5621 | void |
---|
5622 | gtk_html_images_unref (GtkHTML *html) |
---|
5623 | { |
---|
5624 | html_image_factory_unref_all_images (HTML_IMAGE_FACTORY (html->engine->image_factory)); |
---|
5625 | } |
---|
5626 | |
---|
5627 | void |
---|
5628 | gtk_html_image_ref (GtkHTML *html, const gchar *url) |
---|
5629 | { |
---|
5630 | html_image_factory_ref_image_ptr (HTML_IMAGE_FACTORY (html->engine->image_factory), url); |
---|
5631 | } |
---|
5632 | |
---|
5633 | void |
---|
5634 | gtk_html_image_unref (GtkHTML *html, const gchar *url) |
---|
5635 | { |
---|
5636 | html_image_factory_unref_image_ptr (HTML_IMAGE_FACTORY (html->engine->image_factory), url); |
---|
5637 | } |
---|
5638 | |
---|
5639 | void |
---|
5640 | gtk_html_image_preload (GtkHTML *html, const gchar *url) |
---|
5641 | { |
---|
5642 | html_image_factory_register (HTML_IMAGE_FACTORY (html->engine->image_factory), NULL, url, FALSE); |
---|
5643 | } |
---|
5644 | |
---|
5645 | void |
---|
5646 | gtk_html_set_blocking (GtkHTML *html, gboolean block) |
---|
5647 | { |
---|
5648 | html->engine->block = block; |
---|
5649 | } |
---|
5650 | |
---|
5651 | void |
---|
5652 | gtk_html_set_images_blocking (GtkHTML *html, gboolean block) |
---|
5653 | { |
---|
5654 | html->engine->block_images = block; |
---|
5655 | } |
---|
5656 | |
---|
5657 | gint |
---|
5658 | gtk_html_print_get_pages_num (GtkHTML *html, GnomePrintContext *print_context, gdouble header_height, gdouble footer_height) |
---|
5659 | { |
---|
5660 | return html_engine_print_get_pages_num (html->engine, print_context, header_height, footer_height); |
---|
5661 | } |
---|
5662 | |
---|
5663 | gboolean |
---|
5664 | gtk_html_has_undo (GtkHTML *html) |
---|
5665 | { |
---|
5666 | return html_undo_has_undo_steps (html->engine->undo); |
---|
5667 | } |
---|
5668 | |
---|
5669 | void |
---|
5670 | gtk_html_drop_undo (GtkHTML *html) |
---|
5671 | { |
---|
5672 | html_undo_reset (html->engine->undo); |
---|
5673 | } |
---|
5674 | |
---|
5675 | void |
---|
5676 | gtk_html_flush (GtkHTML *html) |
---|
5677 | { |
---|
5678 | html_engine_flush (html->engine); |
---|
5679 | } |
---|