1
|
1 /*
|
|
2 * gaim
|
|
3 *
|
|
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
|
|
5 *
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
9 * (at your option) any later version.
|
|
10 *
|
|
11 * This program 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
|
|
14 * GNU General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License
|
|
17 * along with this program; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 *
|
|
20 */
|
|
21
|
|
22 #include <stdio.h>
|
|
23 #include <stdlib.h>
|
|
24 #include <string.h>
|
|
25 #include <gtk/gtk.h>
|
|
26 #include <gdk/gdkprivate.h>
|
|
27 #include <gdk/gdkx.h>
|
|
28 #include <gdk/gdkkeysyms.h>
|
|
29 #include <X11/Xlib.h>
|
|
30 #include <X11/Xatom.h>
|
|
31
|
|
32 #include "gaim.h"
|
|
33 #include "gtkhtml.h"
|
|
34
|
|
35 #define MAX_SIZE 7
|
|
36 #define MIN_HTML_WIDTH_LINES 20
|
|
37 #define MIN_HTML_HEIGHT_LINES 10
|
|
38 #define BORDER_WIDTH 2
|
|
39 #define SCROLL_TIME 100
|
|
40 #define SCROLL_PIXELS 5
|
|
41 #define KEY_SCROLL_PIXELS 10
|
|
42
|
|
43 int font_sizes[] = { 80, 100, 120, 140, 200, 300, 400 };
|
|
44
|
|
45 GdkFont *fixed_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
46 GdkFont *fixed_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
47 GdkFont *fixed_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
48 GdkFont *fixed_bold_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
49 GdkFont *prop_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
50 GdkFont *prop_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
51 GdkFont *prop_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
52 GdkFont *prop_bold_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
53
|
|
54 struct font_state {
|
|
55 int size;
|
|
56 int owncolor;
|
|
57 int ownbg;
|
|
58 GdkColor *color;
|
|
59 GdkColor *bgcol;
|
|
60 struct font_state *next;
|
|
61 };
|
|
62
|
|
63 struct font_state *push_state(struct font_state *current)
|
|
64 {
|
|
65 struct font_state *tmp;
|
|
66 tmp = (struct font_state *)g_new0(struct font_state, 1);
|
|
67 tmp->next = current;
|
|
68 tmp->color = current->color;
|
|
69 tmp->bgcol = current->bgcol;
|
|
70 tmp->size = current->size;
|
|
71 tmp->owncolor = 0;
|
|
72 tmp->ownbg = 0;
|
|
73 return tmp;
|
|
74 }
|
|
75
|
|
76 enum {
|
|
77 ARG_0,
|
|
78 ARG_HADJUSTMENT,
|
|
79 ARG_VADJUSTMENT,
|
|
80 };
|
|
81
|
|
82
|
|
83 enum {
|
|
84 TARGET_STRING,
|
|
85 TARGET_TEXT,
|
|
86 TARGET_COMPOUND_TEXT
|
|
87 };
|
|
88
|
|
89
|
|
90 static void gtk_html_class_init (GtkHtmlClass *klass);
|
|
91 static void gtk_html_set_arg (GtkObject *object,
|
|
92 GtkArg *arg,
|
|
93 guint arg_id);
|
|
94 static void gtk_html_get_arg (GtkObject *object,
|
|
95 GtkArg *arg,
|
|
96 guint arg_id);
|
|
97 static void gtk_html_init (GtkHtml *html);
|
|
98 static void gtk_html_destroy (GtkObject *object);
|
|
99 static void gtk_html_finalize (GtkObject *object);
|
|
100 static void gtk_html_realize (GtkWidget *widget);
|
|
101 static void gtk_html_unrealize (GtkWidget *widget);
|
|
102 static void gtk_html_style_set (GtkWidget *widget,
|
|
103 GtkStyle *previous_style);
|
|
104 static void gtk_html_draw_focus (GtkWidget *widget);
|
|
105 static void gtk_html_size_request (GtkWidget *widget,
|
|
106 GtkRequisition *requisition);
|
|
107 static void gtk_html_size_allocate (GtkWidget *widget,
|
|
108 GtkAllocation *allocation);
|
|
109 static void gtk_html_adjustment (GtkAdjustment *adjustment,
|
|
110 GtkHtml *html);
|
|
111 static void gtk_html_disconnect (GtkAdjustment *adjustment,
|
|
112 GtkHtml *html);
|
|
113 static void gtk_html_add_seperator (GtkHtml *html);
|
|
114 static void gtk_html_add_pixmap (GtkHtml *html,
|
|
115 GdkPixmap *pm,
|
|
116 gint fit);
|
|
117 static void gtk_html_add_text (GtkHtml *html,
|
|
118 GdkFont *font,
|
|
119 GdkColor *fore,
|
|
120 GdkColor *back,
|
|
121 gchar *chars,
|
|
122 gint length,
|
|
123 gint uline,
|
|
124 gint strike,
|
|
125 gchar *url);
|
|
126 static void gtk_html_draw_bit (GtkHtml *html,
|
|
127 GtkHtmlBit *htmlbit,
|
|
128 gint redraw);
|
|
129 static void gtk_html_selection_get (GtkWidget *widget,
|
|
130 GtkSelectionData *selection_data,
|
|
131 guint sel_info,
|
|
132 guint32 time);
|
|
133 static gint gtk_html_selection_clear (GtkWidget *widget,
|
|
134 GdkEventSelection *event);
|
|
135 static gint gtk_html_visibility_notify (GtkWidget *widget,
|
|
136 GdkEventVisibility *event);
|
|
137
|
|
138
|
|
139 /* Event handlers */
|
|
140 static void gtk_html_draw (GtkWidget *widget,
|
|
141 GdkRectangle *area);
|
|
142 static gint gtk_html_expose (GtkWidget *widget,
|
|
143 GdkEventExpose *event);
|
|
144 static gint gtk_html_button_press (GtkWidget *widget,
|
|
145 GdkEventButton *event);
|
|
146 static gint gtk_html_button_release (GtkWidget *widget,
|
|
147 GdkEventButton *event);
|
|
148 static gint gtk_html_motion_notify (GtkWidget *widget,
|
|
149 GdkEventMotion *event);
|
|
150 static gint gtk_html_key_press (GtkWidget *widget,
|
|
151 GdkEventKey *event);
|
|
152 static gint gtk_html_leave_notify (GtkWidget *widget,
|
|
153 GdkEventCrossing *event);
|
|
154
|
|
155 static gint gtk_html_tooltip_timeout(gpointer data);
|
|
156
|
|
157
|
|
158 static void clear_area (GtkHtml *html,
|
|
159 GdkRectangle *area);
|
|
160 static void expose_html (GtkHtml *html,
|
|
161 GdkRectangle *area,
|
|
162 gboolean cursor);
|
|
163 static void scroll_down (GtkHtml *html,
|
|
164 gint diff0);
|
|
165 static void scroll_up (GtkHtml *html,
|
|
166 gint diff0);
|
|
167
|
|
168 static void adjust_adj (GtkHtml *html,
|
|
169 GtkAdjustment *adj);
|
|
170 static void resize_html (GtkHtml *html);
|
|
171 static gint html_bit_is_onscreen (GtkHtml *html, GtkHtmlBit *hb);
|
|
172 static void draw_cursor (GtkHtml *html);
|
|
173 static void undraw_cursor (GtkHtml *html);
|
|
174
|
|
175 static GtkWidgetClass *parent_class = NULL;
|
|
176
|
|
177 GtkType gtk_html_get_type(void)
|
|
178 {
|
|
179 static GtkType html_type = 0;
|
|
180
|
|
181 if (!html_type) {
|
|
182 static const GtkTypeInfo html_info = {
|
|
183 "GtkHtml",
|
|
184 sizeof(GtkHtml),
|
|
185 sizeof(GtkHtmlClass),
|
|
186 (GtkClassInitFunc) gtk_html_class_init,
|
|
187 (GtkObjectInitFunc) gtk_html_init,
|
|
188 NULL,
|
|
189 NULL,
|
|
190 NULL,
|
|
191 };
|
|
192 html_type = gtk_type_unique (GTK_TYPE_WIDGET, &html_info);
|
|
193 }
|
|
194 return html_type;
|
|
195 }
|
|
196
|
|
197
|
|
198 static void gtk_html_class_init (GtkHtmlClass *class)
|
|
199 {
|
|
200 GtkObjectClass *object_class;
|
|
201 GtkWidgetClass *widget_class;
|
|
202
|
|
203 object_class = (GtkObjectClass *) class;
|
|
204 widget_class = (GtkWidgetClass *) class;
|
|
205 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
|
|
206
|
|
207
|
|
208 gtk_object_add_arg_type("GtkHtml::hadjustment",
|
|
209 GTK_TYPE_ADJUSTMENT,
|
|
210 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
|
|
211 ARG_HADJUSTMENT);
|
|
212
|
|
213 gtk_object_add_arg_type("GtkHtml::vadjustment",
|
|
214 GTK_TYPE_ADJUSTMENT,
|
|
215 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
|
|
216 ARG_VADJUSTMENT);
|
|
217
|
|
218 object_class->set_arg = gtk_html_set_arg;
|
|
219 object_class->get_arg = gtk_html_get_arg;
|
|
220 object_class->destroy = gtk_html_destroy;
|
|
221 object_class->finalize = gtk_html_finalize;
|
|
222
|
|
223 widget_class->realize = gtk_html_realize;
|
|
224 widget_class->unrealize = gtk_html_unrealize;
|
|
225 widget_class->style_set = gtk_html_style_set;
|
|
226 widget_class->draw_focus = gtk_html_draw_focus;
|
|
227 widget_class->size_request = gtk_html_size_request;
|
|
228 widget_class->size_allocate = gtk_html_size_allocate;
|
|
229 widget_class->draw = gtk_html_draw;
|
|
230 widget_class->expose_event = gtk_html_expose;
|
|
231 widget_class->button_press_event = gtk_html_button_press;
|
|
232 widget_class->button_release_event = gtk_html_button_release;
|
|
233 widget_class->motion_notify_event = gtk_html_motion_notify;
|
|
234 widget_class->leave_notify_event = gtk_html_leave_notify;
|
|
235 widget_class->selection_get = gtk_html_selection_get;
|
|
236 widget_class->selection_clear_event = gtk_html_selection_clear;
|
|
237 widget_class->key_press_event = gtk_html_key_press;
|
|
238 widget_class->visibility_notify_event = gtk_html_visibility_notify;
|
|
239
|
|
240
|
|
241 widget_class->set_scroll_adjustments_signal =
|
|
242 gtk_signal_new ("set_scroll_adjustments",
|
|
243 GTK_RUN_LAST,
|
|
244 object_class->type,
|
|
245 GTK_SIGNAL_OFFSET (GtkHtmlClass, set_scroll_adjustments),
|
|
246 gtk_marshal_NONE__POINTER_POINTER,
|
|
247 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
|
|
248
|
|
249
|
|
250 class->set_scroll_adjustments = gtk_html_set_adjustments;
|
|
251
|
|
252 }
|
|
253
|
|
254 static void gtk_html_set_arg (GtkObject *object,
|
|
255 GtkArg *arg,
|
|
256 guint arg_id)
|
|
257 {
|
|
258 GtkHtml *html;
|
|
259
|
|
260 html = GTK_HTML (object);
|
|
261
|
|
262 switch (arg_id) {
|
|
263 case ARG_HADJUSTMENT:
|
|
264 gtk_html_set_adjustments (html,
|
|
265 GTK_VALUE_POINTER (*arg),
|
|
266 html->vadj);
|
|
267 break;
|
|
268 case ARG_VADJUSTMENT:
|
|
269 gtk_html_set_adjustments (html,
|
|
270 html->hadj,
|
|
271 GTK_VALUE_POINTER (*arg));
|
|
272 break;
|
|
273 default:
|
|
274 break;
|
|
275 }
|
|
276 }
|
|
277
|
|
278 static void gtk_html_get_arg (GtkObject *object,
|
|
279 GtkArg *arg,
|
|
280 guint arg_id)
|
|
281 {
|
|
282 GtkHtml *html;
|
|
283
|
|
284 html = GTK_HTML(object);
|
|
285
|
|
286 switch (arg_id) {
|
|
287 case ARG_HADJUSTMENT:
|
|
288 GTK_VALUE_POINTER (*arg) = html->hadj;
|
|
289 break;
|
|
290 case ARG_VADJUSTMENT:
|
|
291 GTK_VALUE_POINTER (*arg) = html->vadj;
|
|
292 break;
|
|
293 default:
|
|
294 arg->type = GTK_TYPE_INVALID;
|
|
295 break;
|
|
296 }
|
|
297 }
|
|
298
|
|
299 static void gtk_html_init (GtkHtml *html)
|
|
300 {
|
|
301 static const GtkTargetEntry targets[] = {
|
|
302 { "STRING", 0, TARGET_STRING },
|
|
303 { "TEXT", 0, TARGET_TEXT },
|
|
304 { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }
|
|
305 };
|
|
306
|
|
307 static const gint n_targets = sizeof(targets) / sizeof(targets[0]);
|
|
308
|
|
309 GTK_WIDGET_SET_FLAGS(html, GTK_CAN_FOCUS);
|
|
310
|
|
311 html->html_area = NULL;
|
|
312 html->hadj = NULL;
|
|
313 html->vadj = NULL;
|
|
314 html->current_x = 0;
|
|
315 html->current_y = 0;
|
|
316 html->start_sel = html->end_sel = NULL;
|
|
317 html->start_sel_x = html->start_sel_y = -1;
|
|
318 html->num_end = html->num_start = -1;
|
|
319
|
|
320 html->html_bits = NULL;
|
|
321 html->urls = NULL;
|
|
322 html->selected_text = NULL;
|
|
323 html->tooltip_hb = NULL;
|
|
324 html->tooltip_timer = -1;
|
|
325 html->tooltip_window = NULL;
|
|
326 html->cursor_hb = NULL;
|
|
327 html->cursor_pos = 0;
|
|
328
|
|
329 html->pm = NULL;
|
|
330
|
|
331 html->editable = 0;
|
|
332 html->transparent = 0;
|
|
333
|
|
334 html->frozen = 0;
|
|
335
|
|
336 gtk_selection_add_targets (GTK_WIDGET (html), GDK_SELECTION_PRIMARY,
|
|
337 targets, n_targets);
|
|
338
|
|
339
|
|
340
|
|
341 }
|
|
342
|
|
343
|
|
344 GtkWidget *gtk_html_new (GtkAdjustment *hadj,
|
|
345 GtkAdjustment *vadj)
|
|
346 {
|
|
347 GtkWidget *html;
|
|
348
|
|
349 if (hadj)
|
|
350 g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadj), NULL);
|
|
351 if (vadj)
|
|
352 g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadj), NULL);
|
|
353
|
|
354 html = gtk_widget_new (GTK_TYPE_HTML,
|
|
355 "hadjustment", hadj,
|
|
356 "vadjustment", vadj,
|
|
357 NULL);
|
|
358
|
|
359 return html;
|
|
360 }
|
|
361
|
|
362
|
|
363 void gtk_html_set_editable (GtkHtml *html,
|
|
364 gboolean is_editable)
|
|
365 {
|
|
366 g_return_if_fail (html != NULL);
|
|
367 g_return_if_fail (GTK_IS_HTML (html));
|
|
368
|
|
369
|
|
370 html->editable = (is_editable != FALSE);
|
|
371
|
|
372 if (is_editable)
|
|
373 draw_cursor(html);
|
|
374 else
|
|
375 undraw_cursor(html);
|
|
376
|
|
377 }
|
|
378
|
|
379 void gtk_html_set_transparent( GtkHtml *html,
|
|
380 gboolean is_transparent)
|
|
381 {
|
|
382 GdkRectangle rect;
|
|
383 gint width, height;
|
|
384 GtkWidget *widget;
|
|
385
|
|
386 g_return_if_fail (html != NULL);
|
|
387 g_return_if_fail (GTK_IS_HTML (html));
|
|
388
|
|
389
|
|
390 widget = GTK_WIDGET(html);
|
|
391 html->transparent = (is_transparent != FALSE);
|
|
392
|
|
393 if (!GTK_WIDGET_REALIZED(widget))
|
|
394 return;
|
|
395
|
|
396 html->bg_gc = NULL;
|
|
397 gdk_window_get_size (widget->window, &width, &height);
|
|
398 rect.x = 0;
|
|
399 rect.y = 0;
|
|
400 rect.width = width;
|
|
401 rect.height = height;
|
|
402 gdk_window_clear_area (widget->window, rect.x, rect.y, rect.width, rect.height);
|
|
403
|
|
404 expose_html (html, &rect, FALSE);
|
|
405 gtk_html_draw_focus ( (GtkWidget *) html);
|
|
406 }
|
|
407
|
|
408
|
|
409 void gtk_html_set_adjustments (GtkHtml *html,
|
|
410 GtkAdjustment *hadj,
|
|
411 GtkAdjustment *vadj)
|
|
412 {
|
|
413 g_return_if_fail (html != NULL);
|
|
414 g_return_if_fail (GTK_IS_HTML (html));
|
|
415 if (hadj)
|
|
416 g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
|
|
417 else
|
|
418 hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
|
|
419 if (vadj)
|
|
420 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
|
|
421 else
|
|
422 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
|
|
423
|
|
424 if (html->hadj && (html->hadj != hadj)) {
|
|
425 gtk_signal_disconnect_by_data (GTK_OBJECT (html->hadj), html);
|
|
426 gtk_object_unref (GTK_OBJECT (html->hadj));
|
|
427 }
|
|
428
|
|
429 if (html->vadj && (html->vadj != vadj)) {
|
|
430 gtk_signal_disconnect_by_data (GTK_OBJECT (html->vadj), html);
|
|
431 gtk_object_unref (GTK_OBJECT (html->vadj));
|
|
432 }
|
|
433
|
|
434 if (html->hadj != hadj) {
|
|
435 html->hadj = hadj;
|
|
436 gtk_object_ref (GTK_OBJECT (html->hadj));
|
|
437 gtk_object_sink (GTK_OBJECT (html->hadj));
|
|
438
|
|
439 gtk_signal_connect (GTK_OBJECT (html->hadj), "changed",
|
|
440 (GtkSignalFunc) gtk_html_adjustment,
|
|
441 html);
|
|
442 gtk_signal_connect (GTK_OBJECT (html->hadj), "value_changed",
|
|
443 (GtkSignalFunc) gtk_html_adjustment,
|
|
444 html);
|
|
445 gtk_signal_connect (GTK_OBJECT (html->hadj), "disconnect",
|
|
446 (GtkSignalFunc) gtk_html_disconnect,
|
|
447 html);
|
|
448 gtk_html_adjustment (hadj, html);
|
|
449 }
|
|
450
|
|
451 if (html->vadj != vadj) {
|
|
452 html->vadj = vadj;
|
|
453 gtk_object_ref (GTK_OBJECT (html->vadj));
|
|
454 gtk_object_sink (GTK_OBJECT (html->vadj));
|
|
455
|
|
456 gtk_signal_connect (GTK_OBJECT (html->vadj), "changed",
|
|
457 (GtkSignalFunc) gtk_html_adjustment,
|
|
458 html);
|
|
459 gtk_signal_connect (GTK_OBJECT (html->vadj), "value_changed",
|
|
460 (GtkSignalFunc) gtk_html_adjustment,
|
|
461 html);
|
|
462 gtk_signal_connect (GTK_OBJECT (html->vadj), "disconnect",
|
|
463 (GtkSignalFunc) gtk_html_disconnect,
|
|
464 html);
|
|
465 gtk_html_adjustment (vadj, html);
|
|
466 }
|
|
467 }
|
|
468
|
|
469
|
|
470
|
|
471 GdkColor *get_color(int colorv, GdkColormap *map)
|
|
472 {
|
|
473 GdkColor *color;
|
|
474 #if 0
|
|
475 fprintf(stdout,"color is %x\n",colorv);
|
|
476 #endif
|
|
477 color = (GdkColor *)g_new0(GdkColor, 1);
|
|
478 color->red = ((colorv & 0xff0000) >> 16) * 256;
|
|
479 color->green = ((colorv & 0xff00) >> 8) * 256;
|
|
480 color->blue = ((colorv & 0xff)) * 256;
|
|
481 #if 0
|
|
482 fprintf(stdout,"Colors are %d, %d, %d\n",color->red, color->green, color->blue);
|
|
483 #endif
|
|
484 gdk_color_alloc(map, color);
|
|
485 return color;
|
|
486 }
|
|
487
|
|
488
|
|
489
|
|
490 GdkFont *font_load(char *fmt, int size)
|
|
491 {
|
|
492 char buf[256];
|
|
493 g_snprintf(buf, sizeof(buf), fmt, font_sizes[size]);
|
|
494 sprintf(debug_buff,"loading font %s\n",buf);
|
|
495 debug_print(debug_buff);
|
|
496 return gdk_font_load(buf);
|
|
497 }
|
|
498
|
|
499
|
|
500 GdkFont *getfont(int bold, int italic, int fixed, int size)
|
|
501 {
|
|
502 if (size > MAX_SIZE) size = MAX_SIZE;
|
|
503 if (size < 1) size=1;
|
|
504 size--;
|
|
505 if (fixed) {
|
|
506 if (bold) {
|
|
507 if (italic) {
|
|
508 if (!fixed_bold_italic_font[size])
|
|
509 fixed_bold_italic_font[size] = font_load(FIXED_BOLD_ITALIC_FONT,size);
|
|
510 return fixed_bold_italic_font[size];
|
|
511
|
|
512 } else {
|
|
513 if (!fixed_bold_font[size])
|
|
514 fixed_bold_font[size] = font_load (FIXED_BOLD_FONT,size);
|
|
515 return fixed_bold_font[size];
|
|
516 }
|
|
517 } else if (italic) {
|
|
518 if (!fixed_italic_font[size])
|
|
519 fixed_italic_font[size] = font_load(FIXED_ITALIC_FONT,size);
|
|
520
|
|
521 return fixed_italic_font[size];
|
|
522 } else {
|
|
523 if (!fixed_font[size])
|
|
524 fixed_font[size] = font_load(FIXED_FONT,size);
|
|
525 return fixed_font[size];
|
|
526 }
|
|
527 } else {
|
|
528 if (bold) {
|
|
529 if (italic) {
|
|
530 if (!prop_bold_italic_font[size])
|
|
531 prop_bold_italic_font[size] = font_load(PROP_BOLD_ITALIC_FONT,size);
|
|
532 return prop_bold_italic_font[size];
|
|
533
|
|
534 } else {
|
|
535 if (!prop_bold_font[size])
|
|
536 prop_bold_font[size] = font_load (PROP_BOLD_FONT,size);
|
|
537 return prop_bold_font[size];
|
|
538 }
|
|
539 } else if (italic) {
|
|
540 if (!prop_italic_font[size])
|
|
541 prop_italic_font[size] = font_load(PROP_ITALIC_FONT,size);
|
|
542
|
|
543 return prop_italic_font[size];
|
|
544 } else {
|
|
545 if (!prop_font[size])
|
|
546 prop_font[size] = font_load(PROP_FONT,size);
|
|
547 return prop_font[size];
|
|
548 }
|
|
549 }
|
|
550 }
|
|
551
|
|
552
|
|
553
|
|
554
|
|
555 /* 'Borrowed' from ETerm */
|
|
556 GdkWindow *get_desktop_window(GtkWidget *widget)
|
|
557 {
|
|
558 GdkAtom prop, type, prop2;
|
|
559 int format;
|
|
560 gint length;
|
|
561 guchar *data;
|
|
562 GtkWidget *w;
|
|
563
|
|
564 prop = gdk_atom_intern("_XROOTPMAP_ID", 1);
|
|
565 prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1);
|
|
566
|
|
567 if (prop == None && prop2 == None) {
|
|
568 return NULL;
|
|
569 }
|
|
570
|
|
571
|
|
572
|
|
573 for (w = widget; w; w = w->parent) {
|
|
574
|
|
575 if (prop != None) {
|
|
576 gdk_property_get(w->window, prop, AnyPropertyType, 0L, 1L, 0,
|
|
577 &type, &format, &length, &data);
|
|
578 } else if (prop2 != None) {
|
|
579 gdk_property_get(w->window, prop2, AnyPropertyType, 0L, 1L, 0,
|
|
580 &type, &format, &length, &data);
|
|
581 } else {
|
|
582 continue;
|
|
583 }
|
|
584 if (type != None) {
|
|
585 return (w->window);
|
|
586 }
|
|
587 }
|
|
588
|
|
589 return NULL;
|
|
590
|
|
591 }
|
|
592
|
|
593
|
|
594
|
|
595 GdkPixmap *get_desktop_pixmap(GtkWidget *widget)
|
|
596 {
|
|
597 GdkPixmap *p;
|
|
598 GdkAtom prop, type, prop2;
|
|
599 int format;
|
|
600 gint length;
|
|
601 guint32 id;
|
|
602 guchar *data;
|
|
603
|
|
604 prop = gdk_atom_intern("_XROOTPMAP_ID", 1);
|
|
605 prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1);
|
|
606
|
|
607
|
|
608 if (prop == None && prop2 == None) {
|
|
609 return NULL;
|
|
610 }
|
|
611
|
|
612 if (prop != None) {
|
|
613 gdk_property_get(get_desktop_window(widget), prop, AnyPropertyType, 0L, 1L, 0,
|
|
614 &type, &format, &length, &data);
|
|
615 if (type == XA_PIXMAP) {
|
|
616 id = data[0];
|
|
617 id += data[1] << 8;
|
|
618 id += data[2] << 16;
|
|
619 id += data[3] << 24;
|
|
620 p = gdk_pixmap_foreign_new(id);
|
|
621 return p;
|
|
622 }
|
|
623 }
|
|
624 if (prop2 != None) {
|
|
625 /* XGetWindowProperty(Xdisplay, desktop_window, prop2, 0L, 1L, False, AnyPropertyType,
|
|
626 &type, &format, &length, &after, &data);*/
|
|
627 /* if (type == XA_CARDINAL) {*/
|
|
628 /* D_PIXMAP((" Solid color not yet supported.\n"));*/
|
|
629 /* return NULL;
|
|
630 }*/
|
|
631 }
|
|
632 /* D_PIXMAP(("No suitable attribute found.\n"));*/
|
|
633 return NULL;
|
|
634 }
|
|
635
|
|
636
|
|
637 static void clear_focus_area (GtkHtml *html,
|
|
638 gint area_x,
|
|
639 gint area_y,
|
|
640 gint area_width,
|
|
641 gint area_height)
|
|
642 {
|
|
643 GtkWidget *widget = GTK_WIDGET (html);
|
|
644 gint x, y;
|
|
645
|
|
646 gint ythick = BORDER_WIDTH + widget->style->klass->ythickness;
|
|
647 gint xthick = BORDER_WIDTH + widget->style->klass->xthickness;
|
|
648
|
|
649 gint width, height;
|
|
650
|
|
651 if (html->frozen > 0)
|
|
652 return;
|
|
653
|
|
654 if (html->transparent) {
|
|
655 if (html->pm == NULL)
|
|
656 html->pm = get_desktop_pixmap(widget);
|
|
657
|
|
658 if (html->pm == NULL)
|
|
659 return;
|
|
660
|
|
661 if (html->bg_gc == NULL) {
|
|
662 GdkGCValues values;
|
|
663
|
|
664 values.tile = html->pm;
|
|
665 values.fill = GDK_TILED;
|
|
666
|
|
667 html->bg_gc = gdk_gc_new_with_values (html->html_area, &values,
|
|
668 GDK_GC_FILL | GDK_GC_TILE);
|
|
669
|
|
670 }
|
|
671
|
|
672 gdk_window_get_deskrelative_origin(widget->window, &x, &y);
|
|
673
|
|
674 gdk_draw_pixmap(widget->window, html->bg_gc, html->pm,
|
|
675 x + area_x, y + area_y, area_x, area_y, area_width,
|
|
676 area_height);
|
|
677
|
|
678
|
|
679 } else {
|
|
680 gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
|
|
681
|
|
682 gdk_gc_set_ts_origin (html->bg_gc,
|
|
683 (- html->xoffset + xthick) % width,
|
|
684 (- html->yoffset + ythick) % height);
|
|
685
|
|
686 gdk_draw_rectangle (widget->window, html->bg_gc, TRUE,
|
|
687 area_x, area_y, area_width, area_height);
|
|
688 }
|
|
689 }
|
|
690
|
|
691 static void gtk_html_draw_focus (GtkWidget *widget)
|
|
692 {
|
|
693 GtkHtml *html;
|
|
694 gint width, height;
|
|
695 gint x, y;
|
|
696
|
|
697 g_return_if_fail (widget != NULL);
|
|
698 g_return_if_fail (GTK_IS_HTML (widget));
|
|
699
|
|
700 html = GTK_HTML (widget);
|
|
701
|
|
702 if (GTK_WIDGET_DRAWABLE (widget)) {
|
|
703 gint ythick = widget->style->klass->ythickness;
|
|
704 gint xthick = widget->style->klass->xthickness;
|
|
705 gint xextra = BORDER_WIDTH;
|
|
706 gint yextra = BORDER_WIDTH;
|
|
707
|
|
708 x = 0;
|
|
709 y = 0;
|
|
710 width = widget->allocation.width;
|
|
711 height = widget->allocation.height;
|
|
712
|
|
713 if (GTK_WIDGET_HAS_FOCUS (widget)) {
|
|
714 x += 1;
|
|
715 y += 1;
|
|
716 width -= 2;
|
|
717 height -= 2;
|
|
718 xextra -= 1;
|
|
719 yextra -= 1;
|
|
720
|
|
721 gtk_paint_focus (widget->style, widget->window,
|
|
722 NULL, widget, "text",
|
|
723 0, 0,
|
|
724 widget->allocation.width - 1,
|
|
725 widget->allocation.height - 1);
|
|
726 }
|
|
727
|
|
728 gtk_paint_shadow (widget->style, widget->window,
|
|
729 GTK_STATE_NORMAL, GTK_SHADOW_IN,
|
|
730 NULL, widget, "text",
|
|
731 x, y, width, height);
|
|
732
|
|
733 x += xthick;
|
|
734 y += ythick;
|
|
735 width -= 2 * xthick;
|
|
736 height -= 2 * ythick;
|
|
737
|
|
738
|
|
739 if (widget->style->bg_pixmap[GTK_STATE_NORMAL] || html->transparent) {
|
|
740 /* top rect */
|
|
741 clear_focus_area (html, x, y, width, yextra);
|
|
742 /* left rect */
|
|
743 clear_focus_area (html, x, y + yextra,
|
|
744 xextra, y + height - 2 * yextra);
|
|
745 /* right rect */
|
|
746 clear_focus_area (html, x + width - xextra, y + yextra,
|
|
747 xextra, height - 2 * ythick);
|
|
748 /* bottom rect */
|
|
749 clear_focus_area (html, x, x + height - yextra, width, yextra);
|
|
750 }
|
|
751 }
|
|
752 }
|
|
753
|
|
754 static void gtk_html_size_request (GtkWidget *widget,
|
|
755 GtkRequisition *requisition)
|
|
756 {
|
|
757 gint xthickness;
|
|
758 gint ythickness;
|
|
759 gint char_height;
|
|
760 gint char_width;
|
|
761
|
|
762 g_return_if_fail (widget != NULL);
|
|
763 g_return_if_fail (GTK_IS_HTML (widget));
|
|
764 g_return_if_fail (requisition != NULL);
|
|
765
|
|
766 xthickness = widget->style->klass->xthickness + BORDER_WIDTH;
|
|
767 ythickness = widget->style->klass->ythickness + BORDER_WIDTH;
|
|
768
|
|
769 char_height = MIN_HTML_HEIGHT_LINES * (widget->style->font->ascent +
|
|
770 widget->style->font->descent);
|
|
771
|
|
772 char_width = MIN_HTML_WIDTH_LINES * (gdk_text_width (widget->style->font,
|
|
773 "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
774 26) / 26);
|
|
775
|
|
776 requisition->width = char_width + xthickness * 2;
|
|
777 requisition->height = char_height + ythickness * 2;
|
|
778 }
|
|
779
|
|
780 static void gtk_html_size_allocate (GtkWidget *widget,
|
|
781 GtkAllocation *allocation)
|
|
782 {
|
|
783 GtkHtml *html;
|
|
784
|
|
785 g_return_if_fail (widget != NULL);
|
|
786 g_return_if_fail (GTK_IS_HTML (widget));
|
|
787 g_return_if_fail (allocation != NULL);
|
|
788
|
|
789 html = GTK_HTML(widget);
|
|
790
|
|
791 widget->allocation = *allocation;
|
|
792 if (GTK_WIDGET_REALIZED (widget)) {
|
|
793 gdk_window_move_resize (widget->window,
|
|
794 allocation->x, allocation->y,
|
|
795 allocation->width, allocation->height);
|
|
796
|
|
797 gdk_window_move_resize (html->html_area,
|
|
798 widget->style->klass->xthickness + BORDER_WIDTH,
|
|
799 widget->style->klass->ythickness + BORDER_WIDTH,
|
|
800 MAX (1, (gint)widget->allocation.width -
|
|
801 (gint)(widget->style->klass->xthickness +
|
|
802 (gint)BORDER_WIDTH) * 2),
|
|
803 MAX (1, (gint)widget->allocation.height -
|
|
804 (gint)(widget->style->klass->ythickness +
|
|
805 (gint)BORDER_WIDTH) * 2));
|
|
806
|
|
807 resize_html(html);
|
|
808 }
|
|
809 }
|
|
810
|
|
811 static void gtk_html_draw (GtkWidget *widget,
|
|
812 GdkRectangle *area)
|
|
813 {
|
|
814 g_return_if_fail (widget != NULL);
|
|
815 g_return_if_fail (GTK_IS_HTML (widget));
|
|
816 g_return_if_fail (area != NULL);
|
|
817
|
|
818 if (GTK_WIDGET_DRAWABLE (widget))
|
|
819 {
|
|
820 expose_html (GTK_HTML(widget), area, TRUE);
|
|
821 gtk_widget_draw_focus (widget);
|
|
822 }
|
|
823 }
|
|
824
|
|
825
|
|
826 static gint gtk_html_expose (GtkWidget *widget,
|
|
827 GdkEventExpose *event)
|
|
828 {
|
|
829 GtkHtml *html;
|
|
830
|
|
831 g_return_val_if_fail (widget != NULL, FALSE);
|
|
832 g_return_val_if_fail (GTK_IS_HTML (widget), FALSE);
|
|
833 g_return_val_if_fail (event != NULL, FALSE);
|
|
834
|
|
835 html = GTK_HTML(widget);
|
|
836
|
|
837 if (event->window == html->html_area) {
|
|
838 expose_html(html, &event->area, TRUE);
|
|
839 } else if (event->count == 0) {
|
|
840 gtk_widget_draw_focus (widget);
|
|
841 }
|
|
842
|
|
843 return FALSE;
|
|
844
|
|
845 }
|
|
846
|
|
847
|
|
848 static gint gtk_html_selection_clear (GtkWidget *widget,
|
|
849 GdkEventSelection *event)
|
|
850 {
|
|
851 GtkHtml *html;
|
|
852
|
|
853 g_return_val_if_fail (widget != NULL, FALSE);
|
|
854 g_return_val_if_fail (GTK_IS_HTML (widget), FALSE);
|
|
855 g_return_val_if_fail (event != NULL, FALSE);
|
|
856
|
|
857 /* Let the selection handling code know that the selection
|
|
858 * has been changed, since we've overriden the default handler */
|
|
859 if (!gtk_selection_clear (widget, event))
|
|
860 return FALSE;
|
|
861
|
|
862 html = GTK_HTML (widget);
|
|
863
|
|
864 if (event->selection == GDK_SELECTION_PRIMARY) {
|
|
865 if (html->selected_text) {
|
|
866 GList *hbits = html->html_bits;
|
|
867 GtkHtmlBit *hb;
|
|
868
|
|
869 g_free(html->selected_text);
|
|
870 html->selected_text = NULL;
|
|
871 html->start_sel = NULL;
|
|
872 html->end_sel = NULL;
|
|
873 html->num_start = 0;
|
|
874 html->num_end = 0;
|
|
875 while(hbits) {
|
|
876 hb = (GtkHtmlBit *)hbits->data;
|
|
877 if (hb->was_selected)
|
|
878 gtk_html_draw_bit(html, hb, 1);
|
|
879 hbits = hbits->prev;
|
|
880 }
|
|
881 hbits = g_list_last(html->html_bits);
|
|
882 }
|
|
883 }
|
|
884
|
|
885 return TRUE;
|
|
886 }
|
|
887
|
|
888
|
|
889
|
|
890 static void gtk_html_selection_get (GtkWidget *widget,
|
|
891 GtkSelectionData *selection_data,
|
|
892 guint sel_info,
|
|
893 guint32 time)
|
|
894 {
|
|
895 gchar *str;
|
|
896 gint len;
|
|
897 GtkHtml *html;
|
|
898
|
|
899 g_return_if_fail (widget != NULL);
|
|
900 g_return_if_fail (GTK_IS_HTML (widget));
|
|
901
|
|
902 html = GTK_HTML(widget);
|
|
903
|
|
904
|
|
905 if (selection_data->selection != GDK_SELECTION_PRIMARY)
|
|
906 return;
|
|
907
|
|
908 str = html->selected_text;
|
|
909
|
|
910 if (!str)
|
|
911 return;
|
|
912
|
|
913 len = strlen(str);
|
|
914
|
|
915 if (sel_info == TARGET_STRING) {
|
|
916 gtk_selection_data_set(selection_data,
|
|
917 GDK_SELECTION_TYPE_STRING,
|
|
918 8*sizeof(gchar), (guchar *)str, len);
|
|
919 } else if ((sel_info == TARGET_TEXT) || (sel_info == TARGET_COMPOUND_TEXT)) {
|
|
920 guchar *text;
|
|
921 GdkAtom encoding;
|
|
922 gint format;
|
|
923 gint new_length;
|
|
924
|
|
925 gdk_string_to_compound_text (str, &encoding, &format, &text, &new_length);
|
|
926 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
|
|
927 gdk_free_compound_text (text);
|
|
928 }
|
|
929
|
|
930
|
|
931
|
|
932 }
|
|
933
|
|
934 static void do_select(GtkHtml *html,
|
|
935 int x,
|
|
936 int y)
|
|
937 {
|
|
938 GList *hbits = g_list_last(html->html_bits);
|
|
939 int epos, spos;
|
|
940 GtkHtmlBit *hb;
|
|
941
|
|
942 if (!hbits)
|
|
943 return;
|
|
944
|
|
945 hb = (GtkHtmlBit *)hbits->data;
|
|
946
|
|
947 while (hbits) {
|
|
948 hb = (GtkHtmlBit *)hbits->data;
|
|
949 if (hb->type == HTML_BIT_TEXT)
|
|
950 break;
|
|
951 hbits = hbits->prev;
|
|
952 }
|
|
953
|
|
954 if (!hb)
|
|
955 return;
|
|
956
|
|
957
|
|
958 if (y > hb->y) {
|
|
959 html->num_end = strlen(hb->text) - 1;
|
|
960 html->end_sel = hb;
|
|
961 } else if (y < 0) {
|
|
962 html->num_end = 0;
|
|
963 html->end_sel = (GtkHtmlBit *)html->html_bits->data;
|
|
964 } else while(hbits) {
|
|
965 hb = (GtkHtmlBit *)hbits->data;
|
|
966 if ((y < hb->y && y > (hb->y - hb->height)) &&
|
|
967 (x > hb->x + hb->width)) {
|
|
968 if (hb->type != HTML_BIT_TEXT) {
|
|
969 html->num_end = 0;
|
|
970 html->end_sel = hb;
|
|
971 break;
|
|
972 }
|
|
973
|
|
974 html->num_end = strlen(hb->text) - 1;
|
|
975 html->end_sel = hb;
|
|
976 break;
|
|
977 } else if ((x > hb->x && x < (hb->x + hb->width)) &&
|
|
978 (y < hb->y && y > (hb->y - hb->height))) {
|
|
979 int i, len;
|
|
980 int w = x - hb->x;
|
|
981
|
|
982 if (hb->type != HTML_BIT_TEXT) {
|
|
983 html->num_end = 0;
|
|
984 html->end_sel = hb;
|
|
985 break;
|
|
986 }
|
|
987
|
|
988 len = strlen(hb->text);
|
|
989
|
|
990 for (i=1; i<=len; i++) {
|
|
991 if (gdk_text_measure(hb->font, hb->text, i) > w) {
|
|
992 html->num_end = i - 1;
|
|
993 html->end_sel = hb;
|
|
994 break;
|
|
995 }
|
|
996 }
|
|
997 break;
|
|
998 }
|
|
999 hbits = hbits->prev;
|
|
1000 }
|
|
1001
|
|
1002 if (html->end_sel == NULL)
|
|
1003 return;
|
|
1004 if (html->start_sel == NULL) {
|
|
1005 html->start_sel = html->end_sel;
|
|
1006 html->num_start = html->num_end;
|
|
1007 }
|
|
1008
|
|
1009 epos = g_list_index(html->html_bits, html->end_sel);
|
|
1010 spos = g_list_index(html->html_bits, html->start_sel);
|
|
1011 g_free(html->selected_text);
|
|
1012 html->selected_text = NULL;
|
|
1013
|
|
1014 if (epos == spos) {
|
|
1015 char *str;
|
|
1016 if (html->start_sel->type != HTML_BIT_TEXT) {
|
|
1017 html->selected_text = NULL;
|
|
1018 return;
|
|
1019 }
|
|
1020 if (html->num_end == html->num_start) {
|
|
1021 str = g_malloc(2);
|
|
1022 if (strlen(html->start_sel->text))
|
|
1023 str[0] = html->start_sel->text[html->num_end];
|
|
1024 else
|
|
1025 str[0] = 0;
|
|
1026 str[1] = 0;
|
|
1027 gtk_html_draw_bit(html, html->start_sel, 0);
|
|
1028 html->selected_text = str;
|
|
1029 } else {
|
|
1030 int st, en;
|
|
1031 char *str;
|
|
1032 if (html->num_end > html->num_start) {
|
|
1033 en = html->num_end;
|
|
1034 st = html->num_start;
|
|
1035 } else {
|
|
1036 en = html->num_start;
|
|
1037 st = html->num_end;
|
|
1038 }
|
|
1039
|
|
1040 str = g_malloc(en - st + 2);
|
|
1041 strncpy(str, html->start_sel->text + st, (en - st + 1));
|
|
1042 str[en - st + 1] = 0;
|
|
1043 gtk_html_draw_bit(html, html->start_sel, 0);
|
|
1044 html->selected_text = str;
|
|
1045
|
|
1046 }
|
|
1047 } else {
|
|
1048 GtkHtmlBit *shb, *ehb;
|
|
1049 int en, st;
|
|
1050 int len, nlen;
|
|
1051 char *str;
|
|
1052 if (epos > spos) {
|
|
1053 shb = html->start_sel;
|
|
1054 ehb = html->end_sel;
|
|
1055 en = html->num_end;
|
|
1056 st = html->num_start;
|
|
1057 } else {
|
|
1058 shb = html->end_sel;
|
|
1059 ehb = html->start_sel;
|
|
1060 en = html->num_start;
|
|
1061 st = html->num_end;
|
|
1062 }
|
|
1063
|
|
1064 hbits = g_list_find(html->html_bits, shb);
|
|
1065
|
|
1066 if (!hbits)
|
|
1067 return;
|
|
1068
|
|
1069 if (shb->type == HTML_BIT_TEXT) {
|
|
1070 len = strlen(shb->text) - st + 1;
|
|
1071 str = g_malloc(len);
|
|
1072 strcpy(str, shb->text + st);
|
|
1073 str[len - 1] = 0;
|
|
1074 gtk_html_draw_bit(html, shb, 0);
|
|
1075 if (shb->newline) {
|
|
1076 len+= 1;
|
|
1077 str = g_realloc(str, len);
|
|
1078 str[len - 2] = '\n';
|
|
1079 str[len - 1] = 0;
|
|
1080 }
|
|
1081 } else {
|
|
1082 len = 1;
|
|
1083 str = g_malloc(1);
|
|
1084 str[0] = 0;
|
|
1085 }
|
|
1086 if (hbits->next == NULL) {
|
|
1087 html->selected_text = str;
|
|
1088 return;
|
|
1089 }
|
|
1090
|
|
1091
|
|
1092 hbits = hbits->next;
|
|
1093 while(1) { /* Yah I know is dangerous :P */
|
|
1094 hb = (GtkHtmlBit *)hbits->data;
|
|
1095 if (hb->type != HTML_BIT_TEXT) {
|
|
1096 if (hb == ehb)
|
|
1097 break;
|
|
1098 hbits = hbits->next;
|
|
1099 continue;
|
|
1100 }
|
|
1101 if (hb != ehb) {
|
|
1102 nlen = len + strlen(hb->text);
|
|
1103 str = g_realloc(str, nlen);
|
|
1104 strcpy(str + (len - 1), hb->text);
|
|
1105 len = nlen;
|
|
1106 str[len - 1] = 0;
|
|
1107 gtk_html_draw_bit(html, hb, 0);
|
|
1108 if (hb->newline) {
|
|
1109 len+= 1;
|
|
1110 str = g_realloc(str, len);
|
|
1111 str[len - 2] = '\n';
|
|
1112 str[len - 1] = 0;
|
|
1113 }
|
|
1114 } else {
|
|
1115 nlen = len + en + 1;
|
|
1116 str = g_realloc(str, nlen);
|
|
1117 strncpy(str + (len - 1), hb->text, en + 1);
|
|
1118 len = nlen;
|
|
1119 str[len - 1] = 0;
|
|
1120
|
|
1121 gtk_html_draw_bit(html, hb, 0);
|
|
1122 if (hb->newline && en == strlen(hb->text)) {
|
|
1123 len+= 1;
|
|
1124 str = g_realloc(str, len);
|
|
1125 str[len - 2] = '\n';
|
|
1126 str[len - 1] = 0;
|
|
1127 }
|
|
1128 break;
|
|
1129 }
|
|
1130 hbits = hbits->next;
|
|
1131 }
|
|
1132 html->selected_text = str;
|
|
1133 }
|
|
1134
|
|
1135 }
|
|
1136
|
|
1137 static gint
|
|
1138 scroll_timeout(GtkHtml *html)
|
|
1139 {
|
|
1140 GdkEventMotion event;
|
|
1141 gint x, y;
|
|
1142 GdkModifierType mask;
|
|
1143
|
|
1144 html->timer = 0;
|
|
1145 gdk_window_get_pointer (html->html_area, &x, &y, &mask);
|
|
1146
|
|
1147 if (mask & GDK_BUTTON1_MASK)
|
|
1148 {
|
|
1149 event.is_hint = 0;
|
|
1150 event.x = x;
|
|
1151 event.y = y;
|
|
1152 event.state = mask;
|
|
1153
|
|
1154 gtk_html_motion_notify (GTK_WIDGET (html), &event);
|
|
1155 }
|
|
1156
|
|
1157 return FALSE;
|
|
1158
|
|
1159 }
|
|
1160
|
|
1161
|
|
1162 static gint gtk_html_tooltip_paint_window(GtkHtml *html)
|
|
1163 {
|
|
1164 GtkStyle *style;
|
|
1165 gint y, baseline_skip, gap;
|
|
1166
|
|
1167 style = html->tooltip_window->style;
|
|
1168
|
|
1169 gap = (style->font->ascent + style->font->descent) / 4;
|
|
1170 if (gap < 2)
|
|
1171 gap = 2;
|
|
1172 baseline_skip = style->font->ascent + style->font->descent + gap;
|
|
1173
|
|
1174 if (!html->tooltip_hb)
|
|
1175 return FALSE;
|
|
1176
|
|
1177 gtk_paint_flat_box(style, html->tooltip_window->window,
|
|
1178 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
|
|
1179 NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
|
|
1180 0, 0, -1, -1);
|
|
1181
|
|
1182 y = style->font->ascent + 4;
|
|
1183
|
|
1184 gtk_paint_string (style, html->tooltip_window->window,
|
|
1185 GTK_STATE_NORMAL,
|
|
1186 NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
|
|
1187 4, y, "HTML Link:");
|
|
1188 y += baseline_skip;
|
|
1189 gtk_paint_string (style, html->tooltip_window->window,
|
|
1190 GTK_STATE_NORMAL,
|
|
1191 NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
|
|
1192 4, y, html->tooltip_hb->url);
|
|
1193
|
|
1194 return FALSE;
|
|
1195
|
|
1196
|
|
1197 }
|
|
1198
|
|
1199 static gint gtk_html_tooltip_timeout(gpointer data)
|
|
1200 {
|
|
1201 GtkHtml *html = (GtkHtml *)data;
|
|
1202
|
|
1203
|
|
1204 GDK_THREADS_ENTER();
|
|
1205
|
|
1206 if (html->tooltip_hb && GTK_WIDGET_DRAWABLE(GTK_WIDGET(html))) {
|
|
1207 GtkWidget *widget;
|
|
1208 GtkStyle *style;
|
|
1209 gint gap, x, y, w, h, scr_w, scr_h, baseline_skip;
|
|
1210
|
|
1211 if (html->tooltip_window)
|
|
1212 gtk_widget_destroy(html->tooltip_window);
|
|
1213
|
|
1214 html->tooltip_window = gtk_window_new (GTK_WINDOW_POPUP);
|
|
1215 gtk_widget_set_app_paintable (html->tooltip_window, TRUE);
|
|
1216 gtk_window_set_policy (GTK_WINDOW (html->tooltip_window), FALSE, FALSE, TRUE);
|
|
1217 gtk_widget_set_name (html->tooltip_window, "gtk-tooltips");
|
|
1218 gtk_signal_connect_object (GTK_OBJECT (html->tooltip_window),
|
|
1219 "expose_event",
|
|
1220 GTK_SIGNAL_FUNC (gtk_html_tooltip_paint_window),
|
|
1221 GTK_OBJECT (html));
|
|
1222 gtk_signal_connect_object (GTK_OBJECT (html->tooltip_window),
|
|
1223 "draw",
|
|
1224 GTK_SIGNAL_FUNC (gtk_html_tooltip_paint_window),
|
|
1225 GTK_OBJECT (html));
|
|
1226
|
|
1227 gtk_widget_ensure_style (html->tooltip_window);
|
|
1228 style = html->tooltip_window->style;
|
|
1229
|
|
1230 widget = GTK_WIDGET(html);
|
|
1231
|
|
1232 scr_w = gdk_screen_width ();
|
|
1233 scr_h = gdk_screen_height ();
|
|
1234
|
|
1235 gap = (style->font->ascent + style->font->descent) / 4;
|
|
1236 if (gap < 2)
|
|
1237 gap = 2;
|
|
1238 baseline_skip = style->font->ascent + style->font->descent + gap;
|
|
1239
|
|
1240 w = 8 + MAX(gdk_string_width(style->font, "HTML Link:"),
|
|
1241 gdk_string_width(style->font, html->tooltip_hb->url));
|
|
1242 ;
|
|
1243 h = 8 - gap;
|
|
1244 h += (baseline_skip * 2);
|
|
1245
|
|
1246 gdk_window_get_pointer (NULL, &x, &y, NULL);
|
|
1247 /*gdk_window_get_origin (widget->window, NULL, &y);*/
|
|
1248 if (GTK_WIDGET_NO_WINDOW (widget))
|
|
1249 y += widget->allocation.y;
|
|
1250
|
|
1251 x -= ((w >> 1) + 4);
|
|
1252
|
|
1253 if ((x + w) > scr_w)
|
|
1254 x -= (x + w) - scr_w;
|
|
1255 else if (x < 0)
|
|
1256 x = 0;
|
|
1257
|
|
1258 if ((y + h + 4) > scr_h)
|
|
1259 y = y - html->tooltip_hb->font->ascent + html->tooltip_hb->font->descent;
|
|
1260 else
|
|
1261 y = y + html->tooltip_hb->font->ascent + html->tooltip_hb->font->descent;
|
|
1262
|
|
1263 gtk_widget_set_usize (html->tooltip_window, w, h);
|
|
1264 gtk_widget_popup (html->tooltip_window, x, y);
|
|
1265
|
|
1266 }
|
|
1267
|
|
1268 html->tooltip_timer = -1;
|
|
1269
|
|
1270 GDK_THREADS_LEAVE();
|
|
1271
|
|
1272 return FALSE;
|
|
1273 }
|
|
1274
|
|
1275
|
|
1276 static gint gtk_html_leave_notify (GtkWidget *widget,
|
|
1277 GdkEventCrossing *event)
|
|
1278 {
|
|
1279 GtkHtml *html;
|
|
1280
|
|
1281 html = GTK_HTML(widget);
|
|
1282
|
|
1283 if (html->tooltip_timer != -1)
|
|
1284 gtk_timeout_remove(html->tooltip_timer);
|
|
1285 if (html->tooltip_window) {
|
|
1286 gtk_widget_destroy(html->tooltip_window);
|
|
1287 html->tooltip_window = NULL;
|
|
1288 }
|
|
1289
|
|
1290
|
|
1291 html->tooltip_hb = NULL;
|
|
1292 return TRUE;
|
|
1293 }
|
|
1294
|
|
1295
|
|
1296 static gint gtk_html_motion_notify (GtkWidget *widget,
|
|
1297 GdkEventMotion *event)
|
|
1298 {
|
|
1299 int x, y;
|
|
1300 gint width, height;
|
|
1301 GdkModifierType state;
|
|
1302 int realx, realy;
|
|
1303 GtkHtml *html = GTK_HTML(widget);
|
|
1304
|
|
1305 if (event->is_hint)
|
|
1306 gdk_window_get_pointer (event->window, &x, &y, &state);
|
|
1307 else
|
|
1308 {
|
|
1309 x = event->x;
|
|
1310 y = event->y;
|
|
1311 state = event->state;
|
|
1312 }
|
|
1313
|
|
1314 gdk_window_get_size(html->html_area, &width, &height);
|
|
1315
|
|
1316 realx = x;
|
|
1317 realy = y + html->yoffset;
|
|
1318
|
|
1319
|
|
1320 if (state & GDK_BUTTON1_MASK) {
|
|
1321 if (realx != html->start_sel_x || realy != html->start_sel_y) {
|
|
1322 char *tmp = NULL;
|
|
1323
|
|
1324 if (y < 0 || y > height) {
|
|
1325 int diff;
|
|
1326 if (html->timer == 0) {
|
|
1327 html->timer = gtk_timeout_add(100,
|
|
1328 (GtkFunction)scroll_timeout,
|
|
1329 html);
|
|
1330 if (y < 0)
|
|
1331 diff = y / 2;
|
|
1332 else
|
|
1333 diff = (y - height) / 2;
|
|
1334
|
|
1335 if (html->vadj->value + diff >
|
|
1336 html->vadj->upper - height + 20)
|
|
1337 gtk_adjustment_set_value(html->vadj,
|
|
1338 html->vadj->upper - height + 20);
|
|
1339 else
|
|
1340 gtk_adjustment_set_value(html->vadj,
|
|
1341 html->vadj->value + diff);
|
|
1342
|
|
1343 }
|
|
1344 }
|
|
1345
|
|
1346 if (html->selected_text != NULL)
|
|
1347 tmp = g_strdup(html->selected_text);
|
|
1348 do_select(html, realx, realy);
|
|
1349 if (tmp) {
|
|
1350 if (!html->selected_text || strcmp(tmp, html->selected_text)) {
|
|
1351 GtkHtmlBit *hb;
|
|
1352 GList *hbits = html->html_bits;
|
|
1353 while(hbits) {
|
|
1354 hb = (GtkHtmlBit *)hbits->data;
|
|
1355 if (hb->was_selected)
|
|
1356 gtk_html_draw_bit(html, hb, 0);
|
|
1357 hbits = hbits->next;
|
|
1358 }
|
|
1359 }
|
|
1360 g_free(tmp);
|
|
1361 }
|
|
1362 }
|
|
1363 } else {
|
|
1364 GtkHtmlBit *hb;
|
|
1365 GList *urls;
|
|
1366
|
|
1367 urls = html->urls;
|
|
1368 while(urls) {
|
|
1369 hb = (GtkHtmlBit *)urls->data;
|
|
1370 if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
|
1371 (realy < hb->y && realy > (hb->y - hb->height))) {
|
|
1372 if (html->tooltip_hb != hb) {
|
|
1373 html->tooltip_hb = hb;
|
|
1374 if (html->tooltip_timer != -1)
|
|
1375 gtk_timeout_remove(html->tooltip_timer);
|
|
1376 if (html->tooltip_window) {
|
|
1377 gtk_widget_destroy(html->tooltip_window);
|
|
1378 html->tooltip_window = NULL;
|
|
1379 }
|
|
1380 html->tooltip_timer = gtk_timeout_add(HTML_TOOLTIP_DELAY, gtk_html_tooltip_timeout, html);
|
|
1381 }
|
|
1382 gdk_window_set_cursor(html->html_area, gdk_cursor_new(GDK_HAND2));
|
|
1383 return TRUE;
|
|
1384 }
|
|
1385 urls = urls->next;
|
|
1386 }
|
|
1387 if (html->tooltip_timer != -1)
|
|
1388 gtk_timeout_remove(html->tooltip_timer);
|
|
1389 if (html->tooltip_window) {
|
|
1390 gtk_widget_destroy(html->tooltip_window);
|
|
1391 html->tooltip_window = NULL;
|
|
1392 }
|
|
1393
|
|
1394
|
|
1395 html->tooltip_hb = NULL;
|
|
1396 gdk_window_set_cursor(html->html_area, NULL);
|
|
1397
|
|
1398
|
|
1399 }
|
|
1400
|
|
1401 return TRUE;
|
|
1402 }
|
|
1403
|
|
1404 static gint gtk_html_button_release (GtkWidget *widget,
|
|
1405 GdkEventButton *event)
|
|
1406 {
|
|
1407 GtkHtml *html;
|
|
1408
|
|
1409 html = GTK_HTML(widget);
|
|
1410
|
|
1411 if (html->frozen > 0)
|
|
1412 return TRUE;
|
|
1413
|
|
1414 if (event->button == 1) {
|
|
1415 int realx, realy;
|
|
1416 GtkHtmlBit *hb;
|
|
1417 GList *urls = html->urls;
|
|
1418
|
|
1419 realx = event->x;
|
|
1420 realy = event->y + html->yoffset;
|
|
1421 if (realx != html->start_sel_x || realy != html->start_sel_y) {
|
|
1422 if (gtk_selection_owner_set (widget,
|
|
1423 GDK_SELECTION_PRIMARY,
|
|
1424 event->time)) {
|
|
1425 } else {
|
|
1426 }
|
|
1427 } else {
|
|
1428 if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == widget->window)
|
|
1429 gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY,
|
|
1430 event->time);
|
|
1431
|
|
1432
|
|
1433 while(urls) {
|
|
1434 hb = (GtkHtmlBit *)urls->data;
|
|
1435 if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
|
1436 (realy < hb->y && realy > (hb->y - hb->height))) {
|
|
1437 if (web_browser == BROWSER_NETSCAPE &&
|
|
1438 (general_options & OPT_GEN_BROWSER_POPUP))
|
|
1439 open_url_nw(NULL, hb->url);
|
|
1440 else
|
|
1441 open_url(NULL, hb->url);
|
|
1442 break;
|
|
1443 }
|
|
1444 urls = urls->next;
|
|
1445 }
|
|
1446 }
|
|
1447 }
|
|
1448 return TRUE;
|
|
1449 }
|
|
1450
|
|
1451
|
|
1452
|
|
1453 static gint gtk_html_button_press (GtkWidget *widget,
|
|
1454 GdkEventButton *event)
|
|
1455 {
|
|
1456 GtkHtml *html;
|
|
1457 gfloat value;
|
|
1458
|
|
1459
|
|
1460 html = GTK_HTML(widget);
|
|
1461 value = html->vadj->value;
|
|
1462
|
|
1463 if (html->frozen > 0)
|
|
1464 return TRUE;
|
|
1465
|
|
1466 if (event->button == 4) {
|
|
1467 value -= html->vadj->step_increment;
|
|
1468 if (value < html->vadj->lower)
|
|
1469 value = html->vadj->lower;
|
|
1470 gtk_adjustment_set_value(html->vadj,
|
|
1471 value);
|
|
1472 } else if (event->button == 5) {
|
|
1473 value += html->vadj->step_increment;
|
|
1474 if (value > html->vadj->upper)
|
|
1475 value = html->vadj->upper;
|
|
1476 gtk_adjustment_set_value(html->vadj,
|
|
1477 value);
|
|
1478
|
|
1479 } else if (event->button == 1) {
|
|
1480 GList *hbits = g_list_last(html->html_bits);
|
|
1481 int realx, realy;
|
|
1482 GtkHtmlBit *hb;
|
|
1483
|
|
1484 realx = event->x;
|
|
1485 realy = event->y + html->yoffset;
|
|
1486
|
|
1487 html->start_sel_x = realx;
|
|
1488 html->start_sel_y = realy;
|
|
1489
|
|
1490 if (!hbits)
|
|
1491 return TRUE;
|
|
1492
|
|
1493 if (html->selected_text) {
|
|
1494 g_free(html->selected_text);
|
|
1495 html->selected_text = NULL;
|
|
1496 html->start_sel = NULL;
|
|
1497 html->end_sel = NULL;
|
|
1498 html->num_start = 0;
|
|
1499 html->num_end = 0;
|
|
1500 while(hbits) {
|
|
1501 hb = (GtkHtmlBit *)hbits->data;
|
|
1502 if (hb->was_selected)
|
|
1503 gtk_html_draw_bit(html, hb, 1);
|
|
1504 hbits = hbits->prev;
|
|
1505 }
|
|
1506 hbits = g_list_last(html->html_bits);
|
|
1507 }
|
|
1508
|
|
1509 hb = (GtkHtmlBit *)hbits->data;
|
|
1510 if (realy > hb->y) {
|
|
1511 if (hb->text)
|
|
1512 html->num_start = strlen(hb->text) - 1;
|
|
1513 else
|
|
1514 html->num_start = 0;
|
|
1515 html->start_sel = hb;
|
|
1516 } else while(hbits) {
|
|
1517 hb = (GtkHtmlBit *)hbits->data;
|
|
1518 if ((realy < hb->y && realy > (hb->y - hb->height)) &&
|
|
1519 (realx > hb->x + hb->width)) {
|
|
1520 if (hb->type != HTML_BIT_TEXT) {
|
|
1521 html->num_end = 0;
|
|
1522 html->end_sel = hb;
|
|
1523 break;
|
|
1524 }
|
|
1525
|
|
1526 if (hb->text)
|
|
1527 html->num_start = strlen(hb->text) - 1;
|
|
1528 else
|
|
1529 html->num_start = 0;
|
|
1530
|
|
1531 html->start_sel = hb;
|
|
1532 break;
|
|
1533 } else if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
|
1534 (realy < hb->y && realy > (hb->y - hb->height))) {
|
|
1535 int i, len;
|
|
1536 int w = realx - hb->x;
|
|
1537
|
|
1538 if (hb->type != HTML_BIT_TEXT) {
|
|
1539 html->num_end = 0;
|
|
1540 html->end_sel = hb;
|
|
1541 break;
|
|
1542 }
|
|
1543
|
|
1544 if (hb->text)
|
|
1545 len = strlen(hb->text);
|
|
1546 else
|
|
1547 len = 0;
|
|
1548
|
|
1549 for (i=1; i<=len; i++) {
|
|
1550 if (gdk_text_measure(hb->font, hb->text, i) > w) {
|
|
1551 html->num_start = i - 1;
|
|
1552 html->start_sel = hb;
|
|
1553 break;
|
|
1554 }
|
|
1555 }
|
|
1556 break;
|
|
1557 }
|
|
1558 hbits = hbits->prev;
|
|
1559 }
|
|
1560 } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
|
|
1561 GtkHtmlBit *hb = NULL;
|
|
1562 int realx, realy;
|
|
1563 GList *urls;
|
|
1564
|
|
1565 realx = event->x;
|
|
1566 realy = event->y + html->yoffset;
|
|
1567
|
|
1568 urls = html->urls;
|
|
1569 while(urls) {
|
|
1570 hb = (GtkHtmlBit *)urls->data;
|
|
1571 if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
|
1572 (realy < hb->y && realy > (hb->y - hb->height))) {
|
|
1573 break;
|
|
1574 }
|
|
1575 urls = urls->next;
|
|
1576 hb = NULL;
|
|
1577 }
|
|
1578
|
|
1579 if (hb != NULL) {
|
|
1580 GtkWidget *menu, *button;
|
|
1581
|
|
1582 menu = gtk_menu_new();
|
|
1583
|
|
1584 if (web_browser == BROWSER_NETSCAPE) {
|
|
1585
|
|
1586 button = gtk_menu_item_new_with_label("Open URL in existing window");
|
|
1587 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1588 GTK_SIGNAL_FUNC(open_url), hb->url);
|
|
1589 gtk_menu_append(GTK_MENU(menu), button);
|
|
1590 gtk_widget_show(button);
|
|
1591
|
|
1592 }
|
|
1593
|
|
1594
|
|
1595 button = gtk_menu_item_new_with_label("Open URL in new window");
|
|
1596 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1597 GTK_SIGNAL_FUNC(open_url_nw), hb->url);
|
|
1598 gtk_menu_append(GTK_MENU(menu), button);
|
|
1599 gtk_widget_show(button);
|
|
1600
|
|
1601 if (web_browser == BROWSER_NETSCAPE) {
|
|
1602
|
|
1603 button = gtk_menu_item_new_with_label("Add URL as bookmark");
|
|
1604 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1605 GTK_SIGNAL_FUNC(add_bookmark), hb->url);
|
|
1606 gtk_menu_append(GTK_MENU(menu), button);
|
|
1607 gtk_widget_show(button);
|
|
1608
|
|
1609 }
|
|
1610
|
|
1611 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
|
|
1612 event->button, event->time);
|
|
1613 }
|
|
1614 }
|
|
1615
|
|
1616 return TRUE;
|
|
1617 }
|
|
1618
|
|
1619
|
|
1620 static void gtk_html_draw_bit(GtkHtml *html,
|
|
1621 GtkHtmlBit *hb,
|
|
1622 int redraw)
|
|
1623 {
|
|
1624 int mypos, epos, spos;
|
|
1625 GdkGC *gc = html->gc;
|
|
1626 int shift;
|
|
1627 GtkStateType selected_state;
|
|
1628 GtkWidget *widget = GTK_WIDGET(html);
|
|
1629 GdkRectangle area;
|
|
1630
|
|
1631 if (html->frozen > 0)
|
|
1632 return;
|
|
1633
|
|
1634 if (hb->type == HTML_BIT_TEXT) {
|
|
1635
|
|
1636 if (!strlen(hb->text))
|
|
1637 return;
|
|
1638
|
|
1639 mypos = g_list_index(html->html_bits, hb);
|
|
1640 epos = g_list_index(html->html_bits, html->end_sel);
|
|
1641 spos = g_list_index(html->html_bits, html->start_sel);
|
|
1642
|
|
1643 if (((html->end_sel == NULL) || (html->start_sel == NULL)) ||
|
|
1644 ((epos < mypos) && (spos < mypos)) ||
|
|
1645 ((epos > mypos) && (spos > mypos))) {
|
|
1646 selected_state = GTK_STATE_NORMAL;
|
|
1647 } else {
|
|
1648 selected_state = GTK_STATE_SELECTED;
|
|
1649 }
|
|
1650
|
|
1651
|
|
1652 gdk_text_extents(hb->font, hb->text, 1, &shift, NULL, NULL, NULL, NULL);
|
|
1653
|
|
1654 if (selected_state == GTK_STATE_SELECTED) {
|
|
1655 int schar = 0, echar = 0;
|
|
1656 int startx = 0, xwidth = 0;
|
|
1657
|
|
1658 if (epos > spos ||
|
|
1659 (epos == spos && html->num_end >= html->num_start)) {
|
|
1660 if (mypos == epos) {
|
|
1661 echar = html->num_end;
|
|
1662 xwidth = gdk_text_measure(hb->font, hb->text, html->num_end + 1);
|
|
1663 } else {
|
|
1664 echar = strlen(hb->text);
|
|
1665 xwidth = hb->width;
|
|
1666 }
|
|
1667 if (mypos == spos) {
|
|
1668 schar = html->num_start;
|
|
1669 startx = gdk_text_measure(hb->font, hb->text, html->num_start);
|
|
1670 xwidth -= startx;
|
|
1671 }
|
|
1672 } else {
|
|
1673 if (mypos == spos) {
|
|
1674 echar = html->num_start;
|
|
1675 xwidth = gdk_text_measure(hb->font, hb->text, html->num_start + 1);
|
|
1676 } else {
|
|
1677 echar = strlen(hb->text);
|
|
1678 xwidth = hb->width;
|
|
1679 }
|
|
1680 if (mypos == epos) {
|
|
1681 schar = html->num_end;
|
|
1682 startx = gdk_text_measure(hb->font, hb->text, html->num_end);
|
|
1683 xwidth -= startx;
|
|
1684 }
|
|
1685 }
|
|
1686
|
|
1687 if (!redraw && echar == hb->sel_e && schar == hb->sel_s)
|
|
1688 return;
|
|
1689
|
|
1690 hb->sel_e = echar;
|
|
1691 hb->sel_s = schar;
|
|
1692
|
|
1693 startx += hb->x;
|
|
1694
|
|
1695
|
|
1696 area.x = hb->x - html->xoffset;
|
|
1697 area.y = hb->y - hb->height + 3 - html->yoffset;
|
|
1698 area.width = hb->width+2;
|
|
1699 area.height = hb->height;
|
|
1700 clear_area (html, &area);
|
|
1701
|
|
1702 gtk_paint_flat_box (widget->style, html->html_area,
|
|
1703 selected_state, GTK_SHADOW_NONE,
|
|
1704 NULL, widget, "text",
|
|
1705 startx,
|
|
1706 hb->y - hb->height + 3 - html->yoffset,
|
|
1707 xwidth+2, hb->height);
|
|
1708 hb->was_selected = 1;
|
|
1709 } else if (hb->was_selected) {
|
|
1710 area.x = hb->x - html->xoffset;
|
|
1711 area.y = hb->y - hb->height + 3 - html->yoffset;
|
|
1712 area.width = hb->width+2;
|
|
1713 area.height = hb->height;
|
|
1714 clear_area (html, &area);
|
|
1715
|
|
1716 hb->sel_e = -1;
|
|
1717 hb->sel_s = -1;
|
|
1718
|
|
1719 hb->was_selected = 0;
|
|
1720 }
|
|
1721
|
|
1722
|
|
1723
|
|
1724
|
|
1725 if (selected_state == GTK_STATE_SELECTED && (mypos == epos
|
|
1726 || mypos == spos)) {
|
|
1727 char *s = hb->text;
|
|
1728 int num = 0, width = 0, fsel = 0, esel = strlen(hb->text);
|
|
1729 int lbearing, rbearing, w;
|
|
1730
|
|
1731 if (epos > spos ||
|
|
1732 (epos == spos && html->num_end >= html->num_start)) {
|
|
1733 if (mypos == epos)
|
|
1734 esel = html->num_end;
|
|
1735 if (mypos == spos)
|
|
1736 fsel = html->num_start;
|
|
1737 } else {
|
|
1738 if (mypos == spos)
|
|
1739 esel = html->num_start;
|
|
1740 if (mypos == epos)
|
|
1741 fsel = html->num_end;
|
|
1742 }
|
|
1743
|
|
1744 while(*s) {
|
|
1745
|
|
1746 if (num < fsel || num > esel)
|
|
1747 selected_state = GTK_STATE_NORMAL;
|
|
1748 else
|
|
1749 selected_state = GTK_STATE_SELECTED;
|
|
1750 if (hb->fore != NULL)
|
|
1751 gdk_gc_set_foreground(gc, hb->fore);
|
|
1752 else
|
|
1753 gdk_gc_set_foreground(gc, &widget->style->text[selected_state]);
|
|
1754 if (hb->back != NULL)
|
|
1755 gdk_gc_set_background(gc, hb->back);
|
|
1756 else
|
|
1757 gdk_gc_set_background(gc, &widget->style->bg[selected_state]);
|
|
1758
|
|
1759
|
|
1760 gdk_gc_set_font(gc, hb->font);
|
|
1761
|
|
1762 gdk_text_extents(hb->font, s, 1, &lbearing, &rbearing, &w, NULL, NULL);
|
|
1763
|
|
1764 gdk_draw_text(html->html_area, hb->font, gc, shift + hb->x + width, hb->y - html->yoffset, s, 1);
|
|
1765
|
|
1766 if (hb->uline)
|
|
1767 gdk_draw_line(html->html_area, gc, shift + hb->x + width, hb->y - html->yoffset, shift + hb->x + width + w, hb->y - html->yoffset);
|
|
1768
|
|
1769 if (hb->strike)
|
|
1770 gdk_draw_line(html->html_area, gc, shift + hb->x + width, hb->y - html->yoffset - (hb->height / 3), shift + hb->x + width + w, hb->y - html->yoffset - (hb->height / 3));
|
|
1771
|
|
1772 width += w;
|
|
1773
|
|
1774 s++;
|
|
1775 num++;
|
|
1776 }
|
|
1777
|
|
1778
|
|
1779 } else {
|
|
1780
|
|
1781 if (hb->fore != NULL)
|
|
1782 gdk_gc_set_foreground(gc, hb->fore);
|
|
1783 else
|
|
1784 gdk_gc_set_foreground(gc, &widget->style->text[selected_state]);
|
|
1785 if (hb->back != NULL)
|
|
1786 gdk_gc_set_background(gc, hb->back);
|
|
1787 else
|
|
1788 gdk_gc_set_background(gc, &widget->style->bg[selected_state]);
|
|
1789
|
|
1790
|
|
1791 gdk_gc_set_font(gc, hb->font);
|
|
1792
|
|
1793 gdk_draw_string(html->html_area, hb->font, gc, shift + hb->x , hb->y - html->yoffset, hb->text);
|
|
1794 if (hb->uline)
|
|
1795 gdk_draw_line(html->html_area, gc, shift + hb->x , hb->y - html->yoffset, hb->x + gdk_string_measure(hb->font, hb->text), hb->y - html->yoffset);
|
|
1796
|
|
1797 if (hb->strike)
|
|
1798 gdk_draw_line(html->html_area, gc, shift + hb->x , hb->y - html->yoffset - (hb->height / 3), hb->x + gdk_string_measure(hb->font, hb->text), hb->y - html->yoffset - (hb->height / 3));
|
|
1799
|
|
1800 }
|
|
1801 } else if (hb->type == HTML_BIT_SEP) {
|
|
1802
|
|
1803 gdk_draw_line(html->html_area, gc, hb->x + 2 , hb->y - html->yoffset - (hb->height / 2 - 1), hb->x + hb->width, hb->y - html->yoffset - (hb->height / 2 - 1));
|
|
1804
|
|
1805 } else if (hb->type == HTML_BIT_PIXMAP) {
|
|
1806 gdk_gc_set_background(gc, &widget->style->base[GTK_STATE_NORMAL]);
|
|
1807 gdk_draw_pixmap(html->html_area, gc, hb->pm, 0, 0, hb->x , hb->y - html->yoffset - (hb->height) + 4, hb->width, hb->height - 2);
|
|
1808 }
|
|
1809 }
|
|
1810
|
|
1811
|
|
1812
|
|
1813 gint compare_types(GtkHtmlBit *hb, GtkHtmlBit *hb2)
|
|
1814 {
|
|
1815 /* In this function, it's OK to accidently return a
|
|
1816 * 0, but will cause problems on an accidental 1 */
|
|
1817
|
|
1818 if (!hb || !hb2)
|
|
1819 return 0;
|
|
1820
|
|
1821
|
|
1822 if (hb->uline != hb2->uline)
|
|
1823 return 0;
|
|
1824 if (hb->strike != hb2->strike)
|
|
1825 return 0;
|
|
1826 if (hb->font && hb2->font) {
|
|
1827 if (!gdk_font_equal(hb->font, hb2->font))
|
|
1828 return 0;
|
|
1829 } else if (hb->font && !hb2->font) {
|
|
1830 return 0;
|
|
1831 } else if (!hb->font && hb2->font) {
|
|
1832 return 0;
|
|
1833 }
|
|
1834 if (hb->type != hb2->type)
|
|
1835 return 0;
|
|
1836
|
|
1837 if (hb->fore && hb2->fore) {
|
|
1838 if (!gdk_color_equal(hb->fore, hb2->fore))
|
|
1839 return 0;
|
|
1840 } else if (hb->fore && !hb2->fore) {
|
|
1841 return 0;
|
|
1842 } else if (!hb->fore && hb2->fore) {
|
|
1843 return 0;
|
|
1844 }
|
|
1845
|
|
1846 if (hb->back && hb2->back) {
|
|
1847 if (!gdk_color_equal(hb->back, hb2->back))
|
|
1848 return 0;
|
|
1849 } else if (hb->back && !hb2->back) {
|
|
1850 return 0;
|
|
1851 } else if (!hb->back && hb2->back) {
|
|
1852 return 0;
|
|
1853 }
|
|
1854
|
|
1855 if ((hb->url != NULL && hb2->url == NULL) ||
|
|
1856 (hb->url == NULL && hb2->url != NULL))
|
|
1857 return 0;
|
|
1858
|
|
1859 if (hb->url != NULL && hb2->url != NULL)
|
|
1860 if (strcasecmp(hb->url, hb2->url))
|
|
1861 return 0;
|
|
1862
|
|
1863 return 1;
|
|
1864 }
|
|
1865
|
|
1866 static gint html_bit_is_onscreen(GtkHtml *html, GtkHtmlBit *hb)
|
|
1867 {
|
|
1868 gint width, height;
|
|
1869
|
|
1870 gdk_window_get_size(html->html_area, &width, &height);
|
|
1871
|
|
1872 if (hb->y < html->yoffset) {
|
|
1873 return 0;
|
|
1874 }
|
|
1875
|
|
1876 if ((hb->y - hb->height) > (html->yoffset + height)) {
|
|
1877 return 0;
|
|
1878 }
|
|
1879 return 1;
|
|
1880 }
|
|
1881
|
|
1882 static void draw_cursor(GtkHtml *html)
|
|
1883 {
|
|
1884 if (
|
|
1885 html->editable &&
|
|
1886 html->cursor_hb &&
|
|
1887 GTK_WIDGET_DRAWABLE(html) &&
|
|
1888 html_bit_is_onscreen(html, html->cursor_hb)) {
|
|
1889 gint x, y;
|
|
1890 gint width;
|
|
1891
|
|
1892 GdkFont *font = html->cursor_hb->font;
|
|
1893
|
|
1894 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL, NULL, &width, NULL, NULL);
|
|
1895
|
|
1896 gdk_gc_set_foreground(html->gc, >K_WIDGET(html)->style->text[GTK_STATE_NORMAL]);
|
|
1897
|
|
1898 y = html->cursor_hb->y - html->yoffset;
|
|
1899 x = html->cursor_hb->x + width;
|
|
1900
|
|
1901
|
|
1902 gdk_draw_line (html->html_area, html->gc, x,
|
|
1903 y, x, y - font->ascent);
|
|
1904
|
|
1905 }
|
|
1906 }
|
|
1907
|
|
1908 static void undraw_cursor(GtkHtml *html)
|
|
1909 {
|
|
1910 if (
|
|
1911 html->editable &&
|
|
1912 html->cursor_hb &&
|
|
1913 GTK_WIDGET_DRAWABLE(html) &&
|
|
1914 html_bit_is_onscreen(html, html->cursor_hb)) {
|
|
1915 gint x, y;
|
|
1916 gint width;
|
|
1917 GdkRectangle area;
|
|
1918
|
|
1919 GdkFont *font = html->cursor_hb->font;
|
|
1920
|
|
1921 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL, NULL, &width, NULL, NULL);
|
|
1922
|
|
1923 y = html->cursor_hb->y - html->yoffset;
|
|
1924 x = html->cursor_hb->x + width;
|
|
1925
|
|
1926 area.x = x;
|
|
1927 area.y = y - font->ascent;
|
|
1928 area.height = font->ascent + 1;
|
|
1929 area.width = 1;
|
|
1930
|
|
1931
|
|
1932 clear_area (html, &area);
|
|
1933
|
|
1934 gtk_html_draw_bit(html, html->cursor_hb, 1);
|
|
1935
|
|
1936
|
|
1937 }
|
|
1938 }
|
|
1939
|
|
1940
|
|
1941 static void expose_html(GtkHtml *html,
|
|
1942 GdkRectangle *area,
|
|
1943 gboolean cursor)
|
|
1944 {
|
|
1945 GList *hbits;
|
|
1946 GtkHtmlBit *hb;
|
|
1947 gint width, height;
|
|
1948 gint realy;
|
|
1949
|
|
1950
|
|
1951 if (html->frozen > 0)
|
|
1952 return;
|
|
1953
|
|
1954
|
|
1955 hbits = html->html_bits;
|
|
1956
|
|
1957 gdk_window_get_size(html->html_area, &width, &height);
|
|
1958
|
|
1959 realy = area->y + html->yoffset;
|
|
1960
|
|
1961 clear_area (html, area);
|
|
1962
|
|
1963 while(hbits) {
|
|
1964
|
|
1965 hb = (GtkHtmlBit *)hbits->data;
|
|
1966
|
|
1967 if (html_bit_is_onscreen(html, hb))
|
|
1968 gtk_html_draw_bit(html, hb, 1);
|
|
1969
|
|
1970
|
|
1971 hbits = hbits->next;
|
|
1972 }
|
|
1973 }
|
|
1974
|
|
1975 static void resize_html(GtkHtml *html)
|
|
1976 {
|
|
1977 GList *hbits = html->html_bits;
|
|
1978 GList *html_bits = html->html_bits;
|
|
1979 GtkHtmlBit *hb, *hb2;
|
|
1980 char *str;
|
|
1981 gint height;
|
|
1982
|
|
1983 if(!hbits)
|
|
1984 return;
|
|
1985
|
|
1986
|
|
1987 html->html_bits = NULL;
|
|
1988
|
|
1989 html->current_x = 0;
|
|
1990 html->current_y = 0;
|
|
1991
|
|
1992 html->vadj->upper = 0;
|
|
1993
|
|
1994 gtk_html_freeze(html);
|
|
1995
|
|
1996 while(hbits) {
|
|
1997 hb = (GtkHtmlBit *)hbits->data;
|
|
1998 if (hb->type == HTML_BIT_SEP) {
|
|
1999
|
|
2000 gtk_html_add_seperator(html);
|
|
2001
|
|
2002 g_free(hb);
|
|
2003
|
|
2004 hbits = hbits->next;
|
|
2005 continue;
|
|
2006 }
|
|
2007 if (hb->type == HTML_BIT_PIXMAP) {
|
|
2008
|
|
2009 gtk_html_add_pixmap(html, hb->pm, hb->fit);
|
|
2010
|
|
2011 g_free(hb);
|
|
2012
|
|
2013 hbits = hbits->next;
|
|
2014 continue;
|
|
2015 }
|
|
2016
|
|
2017 if (hb->newline) {
|
|
2018 int i;
|
|
2019
|
|
2020 if (!hb->text) {
|
|
2021 hb->text = g_malloc(1);
|
|
2022 hb->text[0] = 0;
|
|
2023 }
|
|
2024 for (i=0; i<hb->newline; i++) {
|
|
2025 str = hb->text;
|
|
2026 hb->text = g_strconcat(str, "\n", NULL);
|
|
2027 g_free(str);
|
|
2028 }
|
|
2029 }
|
|
2030
|
|
2031 if (hbits->next) {
|
|
2032 hb2 = (GtkHtmlBit *)hbits->next->data;
|
|
2033 } else {
|
|
2034 hb2 = NULL;
|
|
2035 }
|
|
2036
|
|
2037
|
|
2038
|
|
2039 if (!hb->newline && compare_types(hb, hb2)) {
|
|
2040 str = hb2->text;
|
|
2041 hb2->text = g_strconcat(hb->text, hb2->text, NULL);
|
|
2042 g_free(str);
|
|
2043 hb2 = NULL;
|
|
2044 } else if (hb->text) {
|
|
2045 gtk_html_add_text(html, hb->font, hb->fore, hb->back,
|
|
2046 hb->text, strlen(hb->text), hb->uline, hb->strike, hb->url);
|
|
2047 }
|
|
2048
|
|
2049
|
|
2050
|
|
2051 /* Font stays, so do colors (segfaults if I free) */
|
|
2052 if (hb->fore)
|
|
2053 gdk_color_free(hb->fore);
|
|
2054 if (hb->back)
|
|
2055 gdk_color_free(hb->back);
|
|
2056 if (hb->text)
|
|
2057 g_free(hb->text);
|
|
2058 if (hb->url)
|
|
2059 g_free(hb->url);
|
|
2060
|
|
2061 g_free(hb);
|
|
2062
|
|
2063 hbits = hbits->next;
|
|
2064 }
|
|
2065
|
|
2066 g_list_free(html_bits);
|
|
2067
|
|
2068
|
|
2069 gtk_html_thaw(html);
|
|
2070
|
|
2071 gdk_window_get_size(html->html_area, NULL, &height);
|
|
2072 gtk_adjustment_set_value(html->vadj, html->vadj->upper - height);
|
|
2073
|
|
2074 }
|
|
2075
|
|
2076 static GdkGC *create_bg_gc (GtkHtml *html)
|
|
2077 {
|
|
2078 GdkGCValues values;
|
|
2079
|
|
2080 values.tile = GTK_WIDGET (html)->style->bg_pixmap[GTK_STATE_NORMAL];
|
|
2081 values.fill = GDK_TILED;
|
|
2082
|
|
2083 return gdk_gc_new_with_values (html->html_area, &values,
|
|
2084 GDK_GC_FILL | GDK_GC_TILE);
|
|
2085 }
|
|
2086
|
|
2087 static void clear_area (GtkHtml *html,
|
|
2088 GdkRectangle *area)
|
|
2089 {
|
|
2090 GtkWidget *widget = GTK_WIDGET (html);
|
|
2091 gint x, y;
|
|
2092
|
|
2093
|
|
2094 if (html->transparent) {
|
|
2095 if (html->pm == NULL)
|
|
2096 html->pm = get_desktop_pixmap(widget);
|
|
2097
|
|
2098 if (html->pm == NULL)
|
|
2099 return;
|
|
2100
|
|
2101 if (html->bg_gc == NULL) {
|
|
2102 GdkGCValues values;
|
|
2103
|
|
2104 values.tile = html->pm;
|
|
2105 values.fill = GDK_TILED;
|
|
2106
|
|
2107 html->bg_gc = gdk_gc_new_with_values (html->html_area, &values,
|
|
2108 GDK_GC_FILL | GDK_GC_TILE);
|
|
2109
|
|
2110 }
|
|
2111
|
|
2112 gdk_window_get_deskrelative_origin(html->html_area, &x, &y);
|
|
2113
|
|
2114 gdk_draw_pixmap(html->html_area, html->bg_gc, html->pm,
|
|
2115 x + area->x, y + area->y, area->x, area->y, area->width,
|
|
2116 area->height);
|
|
2117
|
|
2118 return;
|
|
2119
|
|
2120 }
|
|
2121 if (html->bg_gc) {
|
|
2122
|
|
2123 gint width, height;
|
|
2124
|
|
2125 gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
|
|
2126
|
|
2127 gdk_gc_set_ts_origin (html->bg_gc,
|
|
2128 (- html->xoffset) % width,
|
|
2129 (- html->yoffset) % height);
|
|
2130
|
|
2131 gdk_draw_rectangle (html->html_area, html->bg_gc, TRUE,
|
|
2132 area->x, area->y, area->width, area->height);
|
|
2133 }
|
|
2134 else
|
|
2135 gdk_window_clear_area (html->html_area, area->x, area->y, area->width, area->height);
|
|
2136 }
|
|
2137
|
|
2138
|
|
2139
|
|
2140
|
|
2141 static void gtk_html_destroy (GtkObject *object)
|
|
2142 {
|
|
2143 GtkHtml *html;
|
|
2144
|
|
2145 g_return_if_fail(object != NULL);
|
|
2146 g_return_if_fail(GTK_IS_HTML (object));
|
|
2147
|
|
2148 html = (GtkHtml *)object;
|
|
2149
|
|
2150
|
|
2151 gtk_signal_disconnect_by_data (GTK_OBJECT (html->hadj), html);
|
|
2152 gtk_signal_disconnect_by_data (GTK_OBJECT (html->vadj), html);
|
|
2153
|
|
2154 if (html->timer) {
|
|
2155 gtk_timeout_remove (html->timer);
|
|
2156 html->timer = 0;
|
|
2157 }
|
|
2158
|
|
2159 if (html->tooltip_timer) {
|
|
2160 gtk_timeout_remove (html->tooltip_timer);
|
|
2161 html->tooltip_timer = -1;
|
|
2162 }
|
|
2163
|
|
2164
|
|
2165 GTK_OBJECT_CLASS(parent_class)->destroy(object);
|
|
2166
|
|
2167 }
|
|
2168
|
|
2169 static void gtk_html_finalize (GtkObject *object)
|
|
2170 {
|
|
2171 GList *hbits;
|
|
2172 GtkHtml *html;
|
|
2173 GtkHtmlBit *hb;
|
|
2174
|
|
2175
|
|
2176 g_return_if_fail (object != NULL);
|
|
2177 g_return_if_fail (GTK_IS_HTML (object));
|
|
2178
|
|
2179 html = (GtkHtml *)object;
|
|
2180
|
|
2181 gtk_object_unref (GTK_OBJECT (html->hadj));
|
|
2182 gtk_object_unref (GTK_OBJECT (html->vadj));
|
|
2183
|
|
2184 hbits = html->html_bits;
|
|
2185
|
|
2186 while (hbits) {
|
|
2187 hb = (GtkHtmlBit *)hbits->data;
|
|
2188 if (hb->fore)
|
|
2189 gdk_color_free(hb->fore);
|
|
2190 if (hb->back)
|
|
2191 gdk_color_free(hb->back);
|
|
2192 if (hb->text)
|
|
2193 g_free(hb->text);
|
|
2194 if (hb->url)
|
|
2195 g_free(hb->url);
|
|
2196 if (hb->pm)
|
|
2197 gdk_pixmap_unref(hb->pm);
|
|
2198
|
|
2199 g_free(hb);
|
|
2200 hbits = hbits->next;
|
|
2201 }
|
|
2202 if (html->html_bits)
|
|
2203 g_list_free(html->html_bits);
|
|
2204
|
|
2205 if (html->urls)
|
|
2206 g_list_free(html->urls);
|
|
2207
|
|
2208 if (html->selected_text)
|
|
2209 g_free(html->selected_text);
|
|
2210
|
|
2211 if (html->gc)
|
|
2212 gdk_gc_destroy(html->gc);
|
|
2213
|
|
2214 if (html->bg_gc)
|
|
2215 gdk_gc_destroy(html->bg_gc);
|
|
2216
|
|
2217 if (html->tooltip_window)
|
|
2218 gtk_widget_destroy(html->tooltip_window);
|
|
2219
|
|
2220 GTK_OBJECT_CLASS(parent_class)->finalize (object);
|
|
2221 }
|
|
2222
|
|
2223 static void gtk_html_realize (GtkWidget *widget)
|
|
2224 {
|
|
2225 GtkHtml *html;
|
|
2226 GdkWindowAttr attributes;
|
|
2227 gint attributes_mask;
|
|
2228
|
|
2229 g_return_if_fail (widget != NULL);
|
|
2230 g_return_if_fail (GTK_IS_HTML (widget));
|
|
2231
|
|
2232 html = GTK_HTML (widget);
|
|
2233 GTK_WIDGET_SET_FLAGS (html, GTK_REALIZED);
|
|
2234
|
|
2235 attributes.window_type = GDK_WINDOW_CHILD;
|
|
2236 attributes.x = widget->allocation.x;
|
|
2237 attributes.y = widget->allocation.y;
|
|
2238 attributes.width = widget->allocation.width;
|
|
2239 attributes.height = widget->allocation.height;
|
|
2240 attributes.wclass = GDK_INPUT_OUTPUT;
|
|
2241 attributes.visual = gtk_widget_get_visual (widget);
|
|
2242 attributes.colormap = gtk_widget_get_colormap (widget);
|
|
2243 attributes.event_mask = gtk_widget_get_events (widget);
|
|
2244 attributes.event_mask |= (GDK_EXPOSURE_MASK |
|
|
2245 GDK_BUTTON_PRESS_MASK |
|
|
2246 GDK_BUTTON_RELEASE_MASK |
|
|
2247 GDK_BUTTON_MOTION_MASK |
|
|
2248 GDK_ENTER_NOTIFY_MASK |
|
|
2249 GDK_LEAVE_NOTIFY_MASK |
|
|
2250 GDK_POINTER_MOTION_MASK |
|
|
2251 GDK_POINTER_MOTION_HINT_MASK |
|
|
2252 GDK_VISIBILITY_NOTIFY_MASK |
|
|
2253 GDK_KEY_PRESS_MASK);
|
|
2254
|
|
2255 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
|
|
2256
|
|
2257 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
|
|
2258 gdk_window_set_user_data (widget->window, html);
|
|
2259
|
|
2260 attributes.x = (widget->style->klass->xthickness + BORDER_WIDTH);
|
|
2261 attributes.y = (widget->style->klass->ythickness + BORDER_WIDTH);
|
|
2262 attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
|
|
2263 attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
|
|
2264
|
|
2265 html->html_area = gdk_window_new (widget->window, &attributes, attributes_mask);
|
|
2266 gdk_window_set_user_data (html->html_area, html);
|
|
2267
|
|
2268 widget->style = gtk_style_attach (widget->style, widget->window);
|
|
2269
|
|
2270 /* Can't call gtk_style_set_background here because it's handled specially */
|
|
2271 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
|
|
2272 gdk_window_set_background (html->html_area, &widget->style->base[GTK_STATE_NORMAL]);
|
|
2273
|
|
2274 if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
|
|
2275 html->bg_gc = create_bg_gc(html);
|
|
2276
|
|
2277 html->gc = gdk_gc_new (html->html_area);
|
|
2278 gdk_gc_set_exposures (html->gc, TRUE);
|
|
2279 gdk_gc_set_foreground (html->gc, &widget->style->text[GTK_STATE_NORMAL]);
|
|
2280
|
|
2281 gdk_window_show(html->html_area);
|
|
2282
|
|
2283 }
|
|
2284
|
|
2285 static void gtk_html_style_set(GtkWidget *widget,
|
|
2286 GtkStyle *previous_style)
|
|
2287 {
|
|
2288 GtkHtml *html;
|
|
2289
|
|
2290 g_return_if_fail (widget != NULL);
|
|
2291 g_return_if_fail (GTK_IS_HTML (widget));
|
|
2292
|
|
2293 html = GTK_HTML (widget);
|
|
2294 if (GTK_WIDGET_REALIZED (widget)) {
|
|
2295 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
|
|
2296 gdk_window_set_background (html->html_area, &widget->style->base[GTK_STATE_NORMAL]);
|
|
2297
|
|
2298 if (html->bg_gc) {
|
|
2299 gdk_gc_destroy (html->bg_gc);
|
|
2300 html->bg_gc = NULL;
|
|
2301 }
|
|
2302
|
|
2303 if (widget->style->bg_pixmap[GTK_STATE_NORMAL]) {
|
|
2304 html->bg_gc = create_bg_gc(html);
|
|
2305 }
|
|
2306
|
|
2307 }
|
|
2308 }
|
|
2309
|
|
2310 static void gtk_html_unrealize (GtkWidget *widget)
|
|
2311 {
|
|
2312 GtkHtml *html;
|
|
2313
|
|
2314 g_return_if_fail (widget != NULL);
|
|
2315 g_return_if_fail (GTK_IS_HTML (widget));
|
|
2316
|
|
2317 html = GTK_HTML (widget);
|
|
2318
|
|
2319 gdk_window_set_user_data (html->html_area, NULL);
|
|
2320 gdk_window_destroy (html->html_area);
|
|
2321 html->html_area = NULL;
|
|
2322
|
|
2323 gdk_gc_destroy (html->gc);
|
|
2324 html->gc = NULL;
|
|
2325
|
|
2326 if (html->bg_gc)
|
|
2327 {
|
|
2328 gdk_gc_destroy (html->bg_gc);
|
|
2329 html->bg_gc = NULL;
|
|
2330 }
|
|
2331
|
|
2332 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
|
|
2333 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
|
|
2334 }
|
|
2335
|
|
2336
|
|
2337
|
|
2338
|
|
2339
|
|
2340 static void gtk_html_add_pixmap(GtkHtml *html,
|
|
2341 GdkPixmap *pm,
|
|
2342 int fit)
|
|
2343 {
|
|
2344 GtkHtmlBit *last_hb;
|
|
2345 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
|
|
2346 GdkWindowPrivate *private = (GdkWindowPrivate *)pm;
|
|
2347
|
|
2348 last_hb = (GtkHtmlBit *)g_list_last(html->html_bits)->data;
|
|
2349
|
|
2350 hb->fit = fit;
|
|
2351 hb->x = html->current_x;
|
|
2352 hb->y = html->current_y;
|
|
2353 if (fit)
|
|
2354 hb->height = last_hb->height;
|
|
2355 else
|
|
2356 hb->height = private->height;
|
|
2357 hb->type = HTML_BIT_PIXMAP;
|
|
2358 hb->width = private->width;
|
|
2359 hb->text = NULL;
|
|
2360 hb->url = NULL;
|
|
2361 hb->fore = NULL;
|
|
2362 hb->back = NULL;
|
|
2363 hb->font = NULL;
|
|
2364 hb->uline = 0;
|
|
2365 hb->strike = 0;
|
|
2366 hb->was_selected = 0;
|
|
2367 hb->newline = 0;
|
|
2368 hb->pm = pm;
|
|
2369
|
|
2370 if (html->current_x == BORDER_WIDTH) {
|
|
2371 html->current_y += hb->height;
|
|
2372 hb->y += hb->height;
|
|
2373 }
|
|
2374
|
|
2375
|
|
2376 html->current_x += hb->width;
|
|
2377
|
|
2378 gtk_html_draw_bit(html, hb, 1);
|
|
2379
|
|
2380 html->html_bits = g_list_append(html->html_bits, hb);
|
|
2381
|
|
2382
|
|
2383 }
|
|
2384
|
|
2385 static void gtk_html_add_seperator(GtkHtml *html)
|
|
2386 {
|
|
2387 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
|
|
2388 gint width, height;
|
|
2389
|
|
2390 html->current_x = 0;
|
|
2391 html->current_y += 5;
|
|
2392
|
|
2393 gdk_window_get_size(html->html_area, &width, &height);
|
|
2394
|
|
2395 hb->x = html->current_x;
|
|
2396 hb->y = html->current_y;
|
|
2397 hb->height = 5;
|
|
2398 hb->type = HTML_BIT_SEP;
|
|
2399 hb->width = width - GTK_SCROLLED_WINDOW(GTK_WIDGET(html)->parent)->vscrollbar->allocation.width - 10;
|
|
2400 hb->text = NULL;
|
|
2401 hb->url = NULL;
|
|
2402 hb->fore = NULL;
|
|
2403 hb->back = NULL;
|
|
2404 hb->font = NULL;
|
|
2405 hb->uline = 0;
|
|
2406 hb->strike = 0;
|
|
2407 hb->was_selected = 0;
|
|
2408 hb->newline = 0;
|
|
2409 hb->pm = NULL;
|
|
2410
|
|
2411 gtk_html_draw_bit(html, hb, 1);
|
|
2412
|
|
2413 html->html_bits = g_list_append(html->html_bits, hb);
|
|
2414
|
|
2415 }
|
|
2416
|
|
2417
|
|
2418 static void gtk_html_add_text (GtkHtml *html,
|
|
2419 GdkFont *cfont,
|
|
2420 GdkColor *fore,
|
|
2421 GdkColor *back,
|
|
2422 char *chars,
|
|
2423 gint length,
|
|
2424 gint uline,
|
|
2425 gint strike,
|
|
2426 char *url)
|
|
2427 {
|
|
2428 char *nextline = NULL, *c, *text, *tmp;
|
|
2429 GdkGC *gc;
|
|
2430 int nl = 0, nl2 = 0;
|
|
2431 int maxwidth;
|
|
2432 gint lb;
|
|
2433 GList *hbits;
|
|
2434 int num = 0, i, height;
|
|
2435 GtkHtmlBit *hb;
|
|
2436 gint hwidth, hheight;
|
|
2437
|
|
2438 if (length == 1 && chars[0] == '\n') {
|
|
2439 GtkHtmlBit *h;
|
|
2440 hbits = g_list_last(html->html_bits);
|
|
2441 if (!hbits)
|
|
2442 return;
|
|
2443 /* I realize this loses a \n sometimes
|
|
2444 * if it's the first thing in the widget.
|
|
2445 * so fucking what. */
|
|
2446
|
|
2447 h = (GtkHtmlBit *)hbits->data;
|
|
2448 h->newline++;
|
|
2449 if (html->current_x > 0)
|
|
2450 html->current_x = 0;
|
|
2451 else
|
|
2452 html->current_y += gdk_string_height(cfont, "yG") + 2;
|
|
2453 return;
|
|
2454 }
|
|
2455
|
|
2456
|
|
2457
|
|
2458 c = text = g_malloc(length + 2);
|
|
2459 strncpy(text, chars, length);
|
|
2460 text[length] = 0;
|
|
2461
|
|
2462
|
|
2463 gc = html->gc;
|
|
2464
|
|
2465 if (gc == NULL)
|
|
2466 gc = html->gc = gdk_gc_new(html->html_area);
|
|
2467
|
|
2468 gdk_gc_set_font(gc, cfont);
|
|
2469
|
|
2470
|
|
2471 while(*c) {
|
|
2472 if (*c == '\n') {
|
|
2473 if (*(c+1) == '\0') {
|
|
2474 nl = 1;
|
|
2475 length--;
|
|
2476 c[0] = '\0';
|
|
2477 break;
|
|
2478 }
|
|
2479 if (*c) {
|
|
2480 gtk_html_add_text(html, cfont, fore, back, text, num + 1, uline, strike, url);
|
|
2481 tmp = text;
|
|
2482 length -= (num+1);
|
|
2483 text = g_malloc(length+2);
|
|
2484 strncpy(text, (c+1), length);
|
|
2485 text[length] = 0;
|
|
2486 c = text;
|
|
2487 num = 0;
|
|
2488 g_free(tmp);
|
|
2489 continue;
|
|
2490 }
|
|
2491 }
|
|
2492
|
|
2493 num++;
|
|
2494 c++;
|
|
2495 }
|
|
2496
|
|
2497 /* Note, yG is chosen because G is damn high, and y is damn low, */
|
|
2498 /* it should be just fine. :) */
|
|
2499
|
|
2500 gdk_window_get_size(html->html_area, &hwidth, &hheight);
|
|
2501
|
|
2502 num = strlen(text);
|
|
2503
|
|
2504 while(GTK_WIDGET(html)->allocation.width < 20) {
|
|
2505 while(gtk_events_pending())
|
|
2506 gtk_main_iteration();
|
|
2507 }
|
|
2508
|
|
2509 maxwidth = (hwidth - html->current_x - 8);
|
|
2510 /*HTK_SCROLLED_WINDOW(GTK_WIDGET(layout)->parent)->vscrollbar->allocation.width) - 8; */
|
|
2511
|
|
2512 while(gdk_text_measure(cfont, text, num) > maxwidth) {
|
|
2513 if (num > 1)
|
|
2514 num--;
|
|
2515 else {
|
|
2516
|
|
2517 html->current_x = 0;
|
|
2518 if (nl) {
|
|
2519 text[length] = '\n';
|
|
2520 length++;
|
|
2521 }
|
|
2522 gtk_html_add_text(html, cfont, fore, back, text, length, uline, strike, url);
|
|
2523 g_free(text);
|
|
2524 return;
|
|
2525 }
|
|
2526
|
|
2527 }
|
|
2528
|
|
2529 height = gdk_string_height(cfont, "yG") + 2;
|
|
2530
|
|
2531
|
|
2532 if ((int)(html->vadj->upper - html->current_y) < (int)(height * 2)) {
|
|
2533 int val;
|
|
2534 val = (height * 2) + html->current_y;
|
|
2535 html->vadj->upper = val;
|
|
2536 adjust_adj(html, html->vadj);
|
|
2537 }
|
|
2538
|
|
2539
|
|
2540 if (html->current_x == 0) {
|
|
2541 html->current_y += height;
|
|
2542 gdk_text_extents(cfont, text, 1, &lb, NULL, NULL, NULL, NULL);
|
|
2543 html->current_x += (2 - lb);
|
|
2544 } else if ((hbits = g_list_last(html->html_bits)) != NULL) {
|
|
2545 int diff, y;
|
|
2546 hb = (GtkHtmlBit *)hbits->data;
|
|
2547 if (height > hb->height) {
|
|
2548 diff = height - hb->height;
|
|
2549 y = hb->y;
|
|
2550 html->current_y += diff;
|
|
2551 while(hbits) {
|
|
2552 hb = (GtkHtmlBit *)hbits->data;
|
|
2553 if (hb->y != y)
|
|
2554 break;
|
|
2555 hb->height = height;
|
|
2556 hb->y += diff;
|
|
2557
|
|
2558 hbits = hbits->prev;
|
|
2559 }
|
|
2560 }
|
|
2561 }
|
|
2562
|
|
2563
|
|
2564
|
|
2565
|
|
2566 if (num != strlen(text)) {
|
|
2567 /* This is kinda cheesy but it may make things
|
|
2568 * much better lookin */
|
|
2569 for (i=2; i<15; i++) {
|
|
2570 if ((num - i) < 0) {
|
|
2571 html->current_x = 0;
|
|
2572 gtk_html_add_text(html, cfont, fore, back, text, strlen(text), uline, strike, url);
|
|
2573 return;
|
|
2574 } else if (text[num - i] == ' ') {
|
|
2575 num = num - (i-1);
|
|
2576 nl2 = 1;
|
|
2577 break;
|
|
2578 }
|
|
2579 }
|
|
2580
|
|
2581 nextline = g_malloc(length - num + 2);
|
|
2582 strncpy(nextline, (char *)(text + num), length - num);
|
|
2583 nextline[length - num] = 0;
|
|
2584 if (nl) {
|
|
2585 nextline[length - num] = '\n';
|
|
2586 nextline[length - num + 1] = 0;
|
|
2587 nl = 0;
|
|
2588 }
|
|
2589
|
|
2590
|
|
2591 text[num] = 0;
|
|
2592 }
|
|
2593
|
|
2594
|
|
2595 if (url != NULL)
|
|
2596 fore = get_color(3355647, gdk_window_get_colormap(html->html_area));
|
|
2597
|
|
2598
|
|
2599 hb = g_new0(GtkHtmlBit, 1);
|
|
2600
|
|
2601 hb->text = g_strdup(text);
|
|
2602
|
|
2603 if (fore)
|
|
2604 hb->fore = gdk_color_copy(fore);
|
|
2605 else
|
|
2606 hb->fore = NULL;
|
|
2607
|
|
2608 if (back)
|
|
2609 hb->back = gdk_color_copy(back);
|
|
2610 else
|
|
2611 hb->back = NULL;
|
|
2612 hb->font = cfont;
|
|
2613 hb->uline = uline;
|
|
2614 hb->strike = strike;
|
|
2615 hb->height = height;
|
|
2616 gdk_text_extents(cfont, text, num, &lb, NULL, &hb->width, NULL, NULL);
|
|
2617 hb->x = html->current_x;
|
|
2618 hb->y = html->current_y;
|
|
2619 hb->type = HTML_BIT_TEXT;
|
|
2620 hb->pm = NULL;
|
|
2621 if (url != NULL) {
|
|
2622 uline = 1;
|
|
2623 hb->uline = 1;
|
|
2624 hb->url = g_strdup(url);
|
|
2625 } else {
|
|
2626 hb->url = NULL;
|
|
2627 }
|
|
2628 html->current_x += hb->width;
|
|
2629
|
|
2630 html->html_bits = g_list_append(html->html_bits, hb);
|
|
2631 if (url != NULL) {
|
|
2632 html->urls = g_list_append(html->urls, hb);
|
|
2633 }
|
|
2634
|
|
2635
|
|
2636
|
|
2637 gtk_html_draw_bit(html, hb, 1);
|
|
2638
|
|
2639 if (nl || nl2) {
|
|
2640 if (nl)
|
|
2641 hb->newline = 1;
|
|
2642 html->current_x = 0;
|
|
2643 } else
|
|
2644 hb->newline = 0;
|
|
2645
|
|
2646
|
|
2647 if (nextline != NULL) {
|
|
2648 gtk_html_add_text(html, cfont, fore, back, nextline, strlen(nextline), uline, strike, url);
|
|
2649 g_free(nextline);
|
|
2650 }
|
|
2651
|
|
2652 g_free(text);
|
|
2653
|
|
2654
|
|
2655 }
|
|
2656
|
|
2657
|
|
2658 void gtk_html_append_text (GtkHtml *html,
|
|
2659 char *text,
|
|
2660 gint options)
|
|
2661 {
|
|
2662 GdkColormap *map;
|
|
2663 GdkFont *cfont;
|
|
2664 GdkRectangle area;
|
|
2665 char ws[BUF_LONG], tag[BUF_LONG], *c, *url = NULL;
|
|
2666 gint intag=0,wpos=0, tpos=0, colorv, bold=0, italic=0, fixed=0, uline=0, strike=0, title=0;
|
|
2667 gint height;
|
|
2668 struct font_state *current, *tmp;
|
|
2669 struct font_state def_state = { 3, 0, 0, NULL, NULL, NULL };
|
|
2670
|
|
2671 current = &def_state;
|
|
2672 map = gdk_window_get_colormap(html->html_area);
|
|
2673 cfont = getfont(bold, italic, fixed, current->size);
|
|
2674 c = text;
|
|
2675
|
|
2676
|
|
2677 while(*c) {
|
|
2678 if (*c == '<') {
|
|
2679 if (!intag) {
|
|
2680 ws[wpos]=0;
|
|
2681 if (wpos) {
|
|
2682 if (title) {
|
|
2683 if (html->title)
|
|
2684 g_free(html->title);
|
|
2685 html->title = g_strdup(ws);
|
|
2686 } else
|
|
2687 gtk_html_add_text(html, cfont, current->color, current->bgcol, ws, strlen(ws), uline, strike, url);
|
|
2688 }
|
|
2689 wpos=0;
|
|
2690 intag=1;
|
|
2691 } else {
|
|
2692 /* Assuming you NEVER have nested tags
|
|
2693 * (and I mean <tag <tag>> by this, not
|
|
2694 * <tag><tag2></tag2><tag>..*/
|
|
2695 tag[tpos] = 0;
|
|
2696 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1, 0, 0, NULL);
|
|
2697 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag, strlen(tag), 0, 0, NULL);
|
|
2698 tpos = 0;
|
|
2699
|
|
2700 tag[0]=*c;
|
|
2701 }
|
|
2702 } else if (*c == '>') {
|
|
2703 if (intag) {
|
|
2704 tag[tpos]=0;
|
|
2705 if (!strcasecmp(tag, "B"))
|
|
2706 bold = 1;
|
|
2707 else if (!strcasecmp(tag, "STRIKE"))
|
|
2708 strike = 1;
|
|
2709 else if (!strcasecmp(tag, "I"))
|
|
2710 italic = 1;
|
|
2711 else if (!strcasecmp(tag, "U"))
|
|
2712 uline = 1;
|
|
2713 else if (!strcasecmp(tag, "PRE"))
|
|
2714 fixed = 1;
|
|
2715 else if (!strcasecmp(tag, "HR"))
|
|
2716 gtk_html_add_seperator(html);
|
|
2717 else if (!strcasecmp(tag, "/B"))
|
|
2718 bold = 0;
|
|
2719 else if (!strcasecmp(tag, "/STRIKE"))
|
|
2720 strike = 0;
|
|
2721 else if (!strcasecmp(tag, "/I"))
|
|
2722 italic = 0;
|
|
2723 else if (!strcasecmp(tag, "/U"))
|
|
2724 uline = 0;
|
|
2725 else if (!strcasecmp(tag, "/PRE"))
|
|
2726 fixed = 0;
|
|
2727 else if (!strcasecmp(tag, "TITLE"))
|
|
2728 title = 1;
|
|
2729 else if (!strcasecmp(tag, "/TITLE"))
|
|
2730 title = 0;
|
|
2731 else if (!strncasecmp(tag, "IMG", 3)) {
|
|
2732
|
|
2733 } else if (!strcasecmp(tag, "H3")) {
|
|
2734 current = push_state(current);
|
|
2735 current->size = 4;
|
|
2736 } else if (!strcasecmp(tag, "/H3")) {
|
|
2737 gtk_html_add_text(html, cfont, current->color, current->bgcol, "\n", 1, 0, 0, NULL);
|
|
2738
|
|
2739 if (current->next) {
|
|
2740 if (current->ownbg)
|
|
2741 g_free(current->bgcol);
|
|
2742 if (current->owncolor)
|
|
2743 g_free(current->color);
|
|
2744 tmp=current;
|
|
2745 current=current->next;
|
|
2746 g_free(tmp);
|
|
2747 }
|
|
2748 } else if (!strcasecmp(tag, "TABLE")) {
|
|
2749 } else if (!strcasecmp(tag, "/TABLE")) {
|
|
2750 } else if (!strcasecmp(tag, "TR")) {
|
|
2751 } else if (!strcasecmp(tag, "/TR")) {
|
|
2752 } else if (!strcasecmp(tag, "/TD")) {
|
|
2753 } else if (!strcasecmp(tag, "TD")){
|
|
2754 gtk_html_add_text(html, cfont, current->color, current->bgcol, " ", 2, 0, 0, NULL);
|
|
2755 } else if (!strncasecmp(tag, "A ", 2)) {
|
|
2756 char *d;
|
|
2757 char *temp = d = g_strdup(tag);
|
|
2758 int flag = 0;
|
|
2759 strtok(tag," ");
|
|
2760 while((d=strtok(NULL," "))) {
|
|
2761 if (strlen(d) < 7)
|
|
2762 break;
|
|
2763 if (!strncasecmp(d, "HREF=\"", strlen("HREF=\""))) {
|
|
2764 d+= strlen("HREF=\"");
|
|
2765 d[strlen(d) - 1] = 0;
|
|
2766 url = g_malloc(strlen(d) + 1);
|
|
2767 strcpy(url, d);
|
|
2768 flag = 1;
|
|
2769 }
|
|
2770 }
|
|
2771 g_free(temp);
|
|
2772 if (!flag) {
|
|
2773 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1, 0, 0, NULL);
|
|
2774 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag, strlen(tag), 0, 0, NULL);
|
|
2775 gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1, 0, 0, NULL);
|
|
2776 }
|
|
2777 } else if (!strcasecmp(tag, "/A")) {
|
|
2778 if (url) {
|
|
2779 g_free(url);
|
|
2780 url = NULL;
|
|
2781 }
|
|
2782 } else if (!strncasecmp(tag,"FONT", strlen("FONT"))) {
|
|
2783 char *d;
|
|
2784 /* Push a new state onto the stack, based on the old state */
|
|
2785 current = push_state(current);
|
|
2786 strtok(tag," ");
|
|
2787 while((d=strtok(NULL," "))) {
|
|
2788 if (!strncasecmp(d,"COLOR=",strlen("COLOR="))) {
|
|
2789 d+=strlen("COLOR=");
|
|
2790 if (*d == '\"') d++;
|
|
2791 if (*d == '#') d++;
|
|
2792 if (d[strlen(d) - 1] == '\"')
|
|
2793 d[strlen(d) - 1] = 0;
|
|
2794 if (sscanf(d, "%x", &colorv) && !(options & HTML_OPTION_NO_COLOURS)) {
|
|
2795 current->color = get_color(colorv, map);
|
|
2796 current->owncolor = 1;
|
|
2797 } else {
|
|
2798 sprintf(debug_buff,"didn't find color in '%s'\n",d);
|
|
2799 debug_print(debug_buff);
|
|
2800 }
|
|
2801 } else
|
|
2802 if (!strncasecmp(d,"BACK=",strlen("BACK="))) {
|
|
2803 d+=strlen("BACK=");
|
|
2804 if (*d == '\"') d++;
|
|
2805 if (*d == '#') d++;
|
|
2806 if (d[strlen(d) - 1] == '\"')
|
|
2807 d[strlen(d) - 1] = 0;
|
|
2808 if (sscanf(d, "%x", &colorv) && !(options & HTML_OPTION_NO_COLOURS)) {
|
|
2809 current->bgcol = get_color(colorv, map);
|
|
2810 current->ownbg = 1;
|
|
2811 } else {
|
|
2812 sprintf(debug_buff,"didn't find color in '%s'\n",d);
|
|
2813 debug_print(debug_buff);
|
|
2814 }
|
|
2815 } else if (!strncasecmp(d,"SIZE=",strlen("SIZE="))) {
|
|
2816 d+=strlen("SIZE=");
|
|
2817 if (*d == '\"') d++;
|
|
2818 if (*d == '+') d++;
|
|
2819 if (sscanf(d, "%d", &colorv)) {
|
|
2820 current->size = colorv;
|
|
2821 } else {
|
|
2822 sprintf(debug_buff,"didn't find size in '%s'\n",d);
|
|
2823 debug_print(debug_buff);
|
|
2824 }
|
|
2825 } else if (strncasecmp(d,"PTSIZE=", strlen("PTSIZE="))) {
|
|
2826 }
|
|
2827 }
|
|
2828 } else if (!strncasecmp(tag,"BODY BGCOLOR", strlen("BODY BGCOLOR"))) {
|
|
2829
|
|
2830 /* Ditch trailing \" */
|
|
2831 tag[strlen(tag)-1]=0;
|
|
2832 if (sscanf(tag + strlen("BODY BGCOLOR=\"#"), "%x", &colorv) && !(options & HTML_OPTION_NO_COLOURS)) {
|
|
2833 current->bgcol = get_color(colorv, map);
|
|
2834 current->ownbg = 1;
|
|
2835 }
|
|
2836 } else if (!strncasecmp(tag, "/FONT", strlen("/FONT"))) {
|
|
2837 /* Pop a font state off the list if possible, freeing
|
|
2838 any resources it used */
|
|
2839 if (current->next) {
|
|
2840 if (current->ownbg)
|
|
2841 g_free(current->bgcol);
|
|
2842 if (current->owncolor)
|
|
2843 g_free(current->color);
|
|
2844 tmp=current;
|
|
2845 current=current->next;
|
|
2846 g_free(tmp);
|
|
2847 }
|
|
2848
|
|
2849 } else if (!strcasecmp(tag, "/BODY")) {
|
|
2850 if (current->next) {
|
|
2851 if (current->ownbg)
|
|
2852 g_free(current->bgcol);
|
|
2853 if (current->owncolor)
|
|
2854 g_free(current->color);
|
|
2855 tmp=current;
|
|
2856 current=current->next;
|
|
2857 g_free(tmp);
|
|
2858 } /* tags we ignore below */
|
|
2859 } else if (!strncasecmp(tag, "BR", 2)) {
|
|
2860 gtk_html_add_text(html, cfont, current->color, current->bgcol, "\n", 1, 0, 0, NULL);
|
|
2861 } else if (strncasecmp(tag, "HTML", 4) && strncasecmp(tag, "/HTML", 5) &&
|
|
2862 strncasecmp(tag, "BODY", 4) && strncasecmp(tag, "/BODY", 5) &&
|
|
2863 strncasecmp(tag, "P", 1) && strncasecmp(tag, "/P", 2) &&
|
|
2864 strncasecmp(tag, "HEAD", 4) && strncasecmp(tag, "/HEAD", 5)) {
|
|
2865 if (tpos) {
|
|
2866 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1, 0, 0, NULL);
|
|
2867 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag, strlen(tag), 0, 0, NULL);
|
|
2868 gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1, 0, 0, NULL);
|
|
2869
|
|
2870 }
|
|
2871 }
|
|
2872 cfont = getfont(bold,italic,fixed,current->size);
|
|
2873 tpos=0;
|
|
2874 intag = 0;
|
|
2875 } else {
|
|
2876 ws[wpos++]=*c;
|
|
2877 }
|
|
2878 } else if (!intag && *c == '&') {
|
|
2879 if (!strncasecmp(c, "&", 5)) {
|
|
2880 ws[wpos++] = '&';
|
|
2881 c+=4;
|
|
2882 } else if (!strncasecmp(c, "<", 4)) {
|
|
2883 ws[wpos++] = '<';
|
|
2884 c+=3;
|
|
2885 } else if (!strncasecmp(c, ">", 4)) {
|
|
2886 ws[wpos++] = '>';
|
|
2887 c+=3;
|
|
2888 } else if (!strncasecmp(c, " ", 6)) {
|
|
2889 ws[wpos++] = ' ';
|
|
2890 c+=5;
|
|
2891 } else {
|
|
2892 ws[wpos++] = *c;
|
|
2893 }
|
|
2894 } else {
|
|
2895 if (intag) {
|
|
2896 tag[tpos++]=*c;
|
|
2897 } else {
|
|
2898 ws[wpos++]=*c;
|
|
2899 }
|
|
2900 }
|
|
2901 c++;
|
|
2902 }
|
|
2903 while(current->next) {
|
|
2904 if (current->ownbg)
|
|
2905 g_free(current->bgcol);
|
|
2906 if (current->owncolor)
|
|
2907 g_free(current->color);
|
|
2908 tmp = current;
|
|
2909 current = current->next;
|
|
2910 g_free(tmp);
|
|
2911 }
|
|
2912 ws[wpos]=0;
|
|
2913 tag[tpos]=0;
|
|
2914 if (wpos) {
|
|
2915 gtk_html_add_text(html, cfont, current->color, current->bgcol, ws, strlen(ws), uline, strike, url);
|
|
2916 }
|
|
2917 if (tpos) {
|
|
2918 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1, 0, 0, NULL);
|
|
2919 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag, strlen(tag), 0, 0, NULL);
|
|
2920 gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1, 0, 0, NULL);
|
|
2921 }
|
|
2922
|
|
2923
|
|
2924
|
|
2925 gdk_window_get_size(html->html_area, NULL, &height);
|
|
2926 area.height = height;
|
|
2927 gtk_adjustment_set_value(html->vadj, html->vadj->upper - area.height);
|
|
2928
|
|
2929 return;
|
|
2930 }
|
|
2931
|
|
2932
|
|
2933 static void adjust_adj (GtkHtml *html,
|
|
2934 GtkAdjustment *adj)
|
|
2935 {
|
|
2936 gint height;
|
|
2937
|
|
2938 gdk_window_get_size (html->html_area, NULL, &height);
|
|
2939
|
|
2940 adj->step_increment = MIN (adj->upper, (float) SCROLL_PIXELS);
|
|
2941 adj->page_increment = MIN (adj->upper, height - (float) KEY_SCROLL_PIXELS);
|
|
2942 adj->page_size = MIN (adj->upper, height);
|
|
2943 adj->value = MIN (adj->value, adj->upper - adj->page_size);
|
|
2944 adj->value = MAX (adj->value, 0.0);
|
|
2945
|
|
2946 gtk_signal_emit_by_name (GTK_OBJECT (adj), "changed");
|
|
2947 }
|
|
2948
|
|
2949
|
|
2950 static void scroll_down (GtkHtml* html,
|
|
2951 gint diff0)
|
|
2952 {
|
|
2953 GdkRectangle rect;
|
|
2954 gint width, height;
|
|
2955
|
|
2956 html->yoffset += diff0;
|
|
2957
|
|
2958 gdk_window_get_size (html->html_area, &width, &height);
|
|
2959
|
|
2960 if (html->transparent) {
|
|
2961 rect.x = 0;
|
|
2962 rect.y = 0;
|
|
2963 rect.width = width;
|
|
2964 rect.height = height;
|
|
2965 } else {
|
|
2966
|
|
2967
|
|
2968 if (height > diff0 && !html->transparent)
|
|
2969 gdk_draw_pixmap (html->html_area,
|
|
2970 html->gc,
|
|
2971 html->html_area,
|
|
2972 0,
|
|
2973 diff0,
|
|
2974 0,
|
|
2975 0,
|
|
2976 width,
|
|
2977 height - diff0);
|
|
2978
|
|
2979 rect.x = 0;
|
|
2980 rect.y = MAX (0, height - diff0);
|
|
2981 rect.width = width;
|
|
2982 rect.height = MIN (height, diff0);
|
|
2983 }
|
|
2984
|
|
2985 expose_html (html, &rect, FALSE);
|
|
2986 gtk_html_draw_focus ( (GtkWidget *) html);
|
|
2987
|
|
2988 }
|
|
2989
|
|
2990 static void scroll_up (GtkHtml* html,
|
|
2991 gint diff0)
|
|
2992 {
|
|
2993 GdkRectangle rect;
|
|
2994 gint width, height;
|
|
2995
|
|
2996 html->yoffset -= diff0;
|
|
2997
|
|
2998
|
|
2999 gdk_window_get_size (html->html_area, &width, &height);
|
|
3000
|
|
3001 if (html->transparent) {
|
|
3002 rect.x = 0;
|
|
3003 rect.y = 0;
|
|
3004 rect.width = width;
|
|
3005 rect.height = height;
|
|
3006 } else {
|
|
3007
|
|
3008 if (height > diff0)
|
|
3009 gdk_draw_pixmap (html->html_area,
|
|
3010 html->gc,
|
|
3011 html->html_area,
|
|
3012 0,
|
|
3013 0,
|
|
3014 0,
|
|
3015 diff0,
|
|
3016 width,
|
|
3017 height - diff0);
|
|
3018
|
|
3019 rect.x = 0;
|
|
3020 rect.y = 0;
|
|
3021 rect.width = width;
|
|
3022 rect.height = MIN (height, diff0);
|
|
3023 }
|
|
3024
|
|
3025 expose_html (html, &rect, FALSE);
|
|
3026 gtk_html_draw_focus ( (GtkWidget *) html);
|
|
3027
|
|
3028 }
|
|
3029
|
|
3030
|
|
3031
|
|
3032 static void gtk_html_adjustment (GtkAdjustment *adjustment,
|
|
3033 GtkHtml *html)
|
|
3034 {
|
|
3035 g_return_if_fail (adjustment != NULL);
|
|
3036 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
|
|
3037 g_return_if_fail (html != NULL);
|
|
3038 g_return_if_fail (GTK_IS_HTML (html));
|
|
3039
|
|
3040 /* Just ignore it if we haven't been size-allocated and realized yet */
|
|
3041 if (html->html_area == NULL)
|
|
3042 return;
|
|
3043
|
|
3044 if (adjustment == html->hadj) {
|
|
3045 g_warning ("horizontal scrolling not implemented");
|
|
3046 } else {
|
|
3047 gint diff = ((gint)adjustment->value) - html->last_ver_value;
|
|
3048
|
|
3049 if (diff != 0) {
|
|
3050 /*undraw_cursor (text, FALSE);*/
|
|
3051
|
|
3052 if (diff > 0) {
|
|
3053 scroll_down (html, diff);
|
|
3054 } else {/* if (diff < 0) */
|
|
3055 scroll_up (html, -diff);
|
|
3056 }
|
|
3057 /*draw_cursor (text, FALSE); */
|
|
3058
|
|
3059 html->last_ver_value = adjustment->value;
|
|
3060 }
|
|
3061 }
|
|
3062 }
|
|
3063
|
|
3064 static gint gtk_html_visibility_notify (GtkWidget *widget,
|
|
3065 GdkEventVisibility *event)
|
|
3066 {
|
|
3067 GtkHtml *html;
|
|
3068 GdkRectangle rect;
|
|
3069 gint width, height;
|
|
3070
|
|
3071 g_return_val_if_fail (widget != NULL, FALSE);
|
|
3072 g_return_val_if_fail (GTK_IS_HTML (widget), FALSE);
|
|
3073
|
|
3074 html = GTK_HTML(widget);
|
|
3075
|
|
3076 if (GTK_WIDGET_REALIZED (widget) && html->transparent) {
|
|
3077 gdk_window_get_size (html->html_area, &width, &height);
|
|
3078 rect.x = 0;
|
|
3079 rect.y = 0;
|
|
3080 rect.width = width;
|
|
3081 rect.height = height;
|
|
3082 expose_html (html, &rect, FALSE);
|
|
3083 gtk_html_draw_focus ( (GtkWidget *) html);
|
|
3084 } else {
|
|
3085 }
|
|
3086
|
|
3087
|
|
3088 return FALSE;
|
|
3089 }
|
|
3090
|
|
3091
|
|
3092
|
|
3093 static void gtk_html_disconnect (GtkAdjustment *adjustment,
|
|
3094 GtkHtml *html)
|
|
3095 {
|
|
3096 g_return_if_fail (adjustment != NULL);
|
|
3097 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
|
|
3098 g_return_if_fail (html != NULL);
|
|
3099 g_return_if_fail (GTK_IS_HTML (html));
|
|
3100
|
|
3101 if (adjustment == html->hadj)
|
|
3102 gtk_html_set_adjustments (html, NULL, html->vadj);
|
|
3103 if (adjustment == html->vadj)
|
|
3104 gtk_html_set_adjustments (html, html->hadj, NULL);
|
|
3105 }
|
|
3106
|
|
3107 static void move_cursor_ver(GtkHtml *html, int count)
|
|
3108 {
|
|
3109 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3110 GtkHtmlBit *hb = NULL, *hb2 = NULL;
|
|
3111 gint y;
|
|
3112 gint len, len2 = 0;
|
|
3113
|
|
3114 undraw_cursor(html);
|
|
3115
|
|
3116 if (!html->html_bits)
|
|
3117 return;
|
|
3118
|
|
3119 if (!html->cursor_hb)
|
|
3120 html->cursor_hb = (GtkHtmlBit *)html->html_bits->data;
|
|
3121
|
|
3122 hb = html->cursor_hb;
|
|
3123
|
|
3124 len = html->cursor_pos;
|
|
3125 hbits = hbits->prev;
|
|
3126 while(hbits) {
|
|
3127 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3128
|
|
3129 if (hb2->y != hb->y)
|
|
3130 break;
|
|
3131
|
|
3132 len += strlen(hb2->text);
|
|
3133
|
|
3134 hbits = hbits->prev;
|
|
3135 }
|
|
3136
|
|
3137 hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3138
|
|
3139 if (count < 0) {
|
|
3140 while(hbits) {
|
|
3141 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3142
|
|
3143 if (hb2->y != hb->y)
|
|
3144 break;
|
|
3145
|
|
3146 hbits = hbits->prev;
|
|
3147 }
|
|
3148 if (!hbits) {
|
|
3149 draw_cursor(html);
|
|
3150 return;
|
|
3151 }
|
|
3152 y = hb2->y;
|
|
3153 hb = hb2;
|
|
3154 while(hbits) {
|
|
3155 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3156
|
|
3157 if (hb2->y != y)
|
|
3158 break;
|
|
3159
|
|
3160 hb = hb2;
|
|
3161
|
|
3162 hbits = hbits->prev;
|
|
3163 }
|
|
3164 hbits = g_list_find(html->html_bits, hb);
|
|
3165 while(hbits) {
|
|
3166 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3167
|
|
3168 if (hb->y != hb2->y) {
|
|
3169 html->cursor_hb = hb;
|
|
3170 html->cursor_pos = strlen(hb->text);
|
|
3171 break;
|
|
3172 }
|
|
3173
|
|
3174
|
|
3175 if (len < len2 + strlen(hb2->text)) {
|
|
3176 html->cursor_hb = hb2;
|
|
3177 html->cursor_pos = len - len2;
|
|
3178 break;
|
|
3179 }
|
|
3180
|
|
3181 len2 += strlen(hb2->text);
|
|
3182
|
|
3183 hb = hb2;
|
|
3184
|
|
3185 hbits = hbits->next;
|
|
3186 }
|
|
3187 } else {
|
|
3188 while(hbits) {
|
|
3189 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3190
|
|
3191 if (hb2->y != hb->y)
|
|
3192 break;
|
|
3193
|
|
3194 hbits = hbits->next;
|
|
3195 }
|
|
3196 if (!hbits) {
|
|
3197 draw_cursor(html);
|
|
3198 return;
|
|
3199 }
|
|
3200 hb = hb2;
|
|
3201 while(hbits) {
|
|
3202 hb2 = (GtkHtmlBit *)hbits->data;
|
|
3203
|
|
3204 if (hb->y != hb2->y) {
|
|
3205 html->cursor_hb = hb;
|
|
3206 html->cursor_pos = strlen(hb->text);
|
|
3207 break;
|
|
3208 }
|
|
3209
|
|
3210
|
|
3211 if (len < len2 + strlen(hb2->text)) {
|
|
3212 html->cursor_hb = hb2;
|
|
3213 html->cursor_pos = len - len2;
|
|
3214 break;
|
|
3215 }
|
|
3216
|
|
3217 len2 += strlen(hb2->text);
|
|
3218
|
|
3219 hb = hb2;
|
|
3220
|
|
3221 hbits = hbits->next;
|
|
3222 }
|
|
3223 }
|
|
3224
|
|
3225 draw_cursor(html);
|
|
3226
|
|
3227 }
|
|
3228
|
|
3229 static void move_cursor_hor(GtkHtml *html, int count)
|
|
3230 {
|
|
3231 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3232 GtkHtmlBit *hb, *hb2;
|
|
3233
|
|
3234 undraw_cursor(html);
|
|
3235
|
|
3236 if (!html->html_bits)
|
|
3237 return;
|
|
3238
|
|
3239 if (!html->cursor_hb)
|
|
3240 html->cursor_hb = (GtkHtmlBit *)html->html_bits->data;
|
|
3241
|
|
3242 html->cursor_pos+=count;
|
|
3243
|
|
3244 if (html->cursor_pos < 0) {
|
|
3245 if (hbits->prev) {
|
|
3246 gint diff;
|
|
3247 hb = html->cursor_hb;
|
|
3248 hb2 = (GtkHtmlBit *)hbits->prev->data;
|
|
3249 diff = html->cursor_pos + strlen(hb2->text) + 1;
|
|
3250 if (hb->y == hb2->y)
|
|
3251 --diff;
|
|
3252
|
|
3253 html->cursor_pos = diff;
|
|
3254
|
|
3255 html->cursor_hb = (GtkHtmlBit *)hbits->prev->data;
|
|
3256 } else {
|
|
3257 html->cursor_pos = 0;
|
|
3258 }
|
|
3259 } else if (html->cursor_pos > strlen(html->cursor_hb->text)) {
|
|
3260 if (hbits->next) {
|
|
3261 gint diff;
|
|
3262 hb = html->cursor_hb;
|
|
3263 hb2 = (GtkHtmlBit *)hbits->next->data;
|
|
3264
|
|
3265 diff = html->cursor_pos - strlen(html->cursor_hb->text) - 1;
|
|
3266 if (hb->y == hb2->y)
|
|
3267 ++diff;
|
|
3268 html->cursor_pos = diff;
|
|
3269 html->cursor_hb = (GtkHtmlBit *)hbits->next->data;
|
|
3270 } else {
|
|
3271 html->cursor_pos = strlen(html->cursor_hb->text);
|
|
3272 }
|
|
3273
|
|
3274 }
|
|
3275
|
|
3276 draw_cursor(html);
|
|
3277 }
|
|
3278
|
|
3279 static void move_beginning_of_line(GtkHtml *html)
|
|
3280 {
|
|
3281 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3282 GtkHtmlBit *hb = NULL;
|
|
3283 gint y;
|
|
3284
|
|
3285 undraw_cursor(html);
|
|
3286
|
|
3287 if (!html->html_bits)
|
|
3288 return;
|
|
3289
|
|
3290 if (!html->cursor_hb)
|
|
3291 html->cursor_hb = (GtkHtmlBit *)html->html_bits->data;
|
|
3292
|
|
3293 y = html->cursor_hb->y;
|
|
3294
|
|
3295 while(hbits) {
|
|
3296 hb = (GtkHtmlBit *)hbits->data;
|
|
3297
|
|
3298 if (y != hb->y) {
|
|
3299 hb = (GtkHtmlBit *)hbits->next->data;
|
|
3300 break;
|
|
3301 }
|
|
3302
|
|
3303 hbits = hbits->prev;
|
|
3304 }
|
|
3305 if (!hbits)
|
|
3306 html->cursor_hb = (GtkHtmlBit*)html->html_bits->data;
|
|
3307 else
|
|
3308 html->cursor_hb = hb;
|
|
3309
|
|
3310 html->cursor_pos = 0;
|
|
3311
|
|
3312
|
|
3313 draw_cursor(html);
|
|
3314
|
|
3315
|
|
3316 }
|
|
3317
|
|
3318 static void move_end_of_line(GtkHtml *html)
|
|
3319 {
|
|
3320 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3321 GtkHtmlBit *hb = NULL;
|
|
3322 gint y;
|
|
3323
|
|
3324 undraw_cursor(html);
|
|
3325
|
|
3326 if (!html->html_bits)
|
|
3327 return;
|
|
3328
|
|
3329 if (!html->cursor_hb)
|
|
3330 html->cursor_hb = (GtkHtmlBit *)html->html_bits->data;
|
|
3331
|
|
3332 y = html->cursor_hb->y;
|
|
3333
|
|
3334 while(hbits) {
|
|
3335 hb = (GtkHtmlBit *)hbits->data;
|
|
3336
|
|
3337 if (y != hb->y) {
|
|
3338 hb = (GtkHtmlBit *)hbits->prev->data;
|
|
3339 break;
|
|
3340 }
|
|
3341
|
|
3342 hbits = hbits->next;
|
|
3343 }
|
|
3344 if (!hbits)
|
|
3345 html->cursor_hb = (GtkHtmlBit*)g_list_last(html->html_bits)->data;
|
|
3346 else
|
|
3347 html->cursor_hb = hb;
|
|
3348
|
|
3349 html->cursor_pos = strlen(html->cursor_hb->text);
|
|
3350
|
|
3351
|
|
3352 draw_cursor(html);
|
|
3353
|
|
3354
|
|
3355 }
|
|
3356
|
|
3357
|
|
3358
|
|
3359 static gint
|
|
3360 gtk_html_key_press (GtkWidget *widget,
|
|
3361 GdkEventKey *event)
|
|
3362 {
|
|
3363 GtkHtml *html;
|
|
3364 gchar key;
|
|
3365 gint return_val;
|
|
3366
|
|
3367 g_return_val_if_fail (widget != NULL, FALSE);
|
|
3368 g_return_val_if_fail (GTK_IS_HTML (widget), FALSE);
|
|
3369 g_return_val_if_fail (event != NULL, FALSE);
|
|
3370
|
|
3371 return_val = FALSE;
|
|
3372
|
|
3373 html = GTK_HTML (widget);
|
|
3374
|
|
3375 key = event->keyval;
|
|
3376 return_val = TRUE;
|
|
3377
|
|
3378
|
|
3379 if (html->editable == FALSE) {
|
|
3380 /*
|
|
3381 switch (event->keyval) {
|
|
3382 case GDK_Home:
|
|
3383 if (event->state & GDK_CONTROL_MASK)
|
|
3384 scroll_int (text, -text->vadj->value);
|
|
3385 else
|
|
3386 return_val = FALSE;
|
|
3387 break;
|
|
3388 case GDK_End:
|
|
3389 if (event->state & GDK_CONTROL_MASK)
|
|
3390 scroll_int (text, +text->vadj->upper);
|
|
3391 else
|
|
3392 return_val = FALSE;
|
|
3393 break;
|
|
3394 case GDK_Page_Up: scroll_int (text, -text->vadj->page_increment); break;
|
|
3395 case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break;
|
|
3396 case GDK_Up: scroll_int (text, -KEY_SCROLL_PIXELS); break;
|
|
3397 case GDK_Down: scroll_int (text, +KEY_SCROLL_PIXELS); break;
|
|
3398 case GDK_Return:
|
|
3399 if (event->state & GDK_CONTROL_MASK)
|
|
3400 gtk_signal_emit_by_name (GTK_OBJECT (text), "activate");
|
|
3401 else
|
|
3402 return_val = FALSE;
|
|
3403 break;
|
|
3404 default:
|
|
3405 return_val = FALSE;
|
|
3406 break;
|
|
3407 }
|
|
3408 */
|
|
3409 } else {
|
|
3410
|
|
3411 switch (event->keyval) {
|
|
3412 case GDK_Home:
|
|
3413 move_beginning_of_line (html);
|
|
3414 break;
|
|
3415 case GDK_End:
|
|
3416 move_end_of_line (html);
|
|
3417 break;
|
|
3418 /*
|
|
3419 case GDK_Page_Up:
|
|
3420 move_cursor_page_ver (html, -1);
|
|
3421 break;
|
|
3422 case GDK_Page_Down:
|
|
3423 move_cursor_page_ver (html, +1);
|
|
3424 break;*/
|
|
3425 /* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
|
|
3426 case GDK_Up:
|
|
3427 move_cursor_ver (html, -1);
|
|
3428 break;
|
|
3429 case GDK_Down:
|
|
3430 move_cursor_ver (html, +1);
|
|
3431 break;
|
|
3432 case GDK_Left:
|
|
3433 move_cursor_hor (html, -1);
|
|
3434 break;
|
|
3435 case GDK_Right:
|
|
3436 move_cursor_hor (html, +1);
|
|
3437 break;
|
|
3438 #if 0
|
|
3439 case GDK_BackSpace:
|
|
3440 if (event->state & GDK_CONTROL_MASK)
|
|
3441 gtk_text_delete_backward_word (text);
|
|
3442 else
|
|
3443 gtk_text_delete_backward_character (text);
|
|
3444 break;
|
|
3445 case GDK_Clear:
|
|
3446 gtk_text_delete_line (text);
|
|
3447 break;
|
|
3448 case GDK_Insert:
|
|
3449 if (event->state & GDK_SHIFT_MASK)
|
|
3450 {
|
|
3451 extend_selection = FALSE;
|
|
3452 gtk_editable_paste_clipboard (editable);
|
|
3453 }
|
|
3454 else if (event->state & GDK_CONTROL_MASK)
|
|
3455 {
|
|
3456 gtk_editable_copy_clipboard (editable);
|
|
3457 }
|
|
3458 else
|
|
3459 {
|
|
3460 /* gtk_toggle_insert(text) -- IMPLEMENT */
|
|
3461 }
|
|
3462 break;
|
|
3463 case GDK_Delete:
|
|
3464 if (event->state & GDK_CONTROL_MASK)
|
|
3465 gtk_text_delete_forward_word (text);
|
|
3466 else if (event->state & GDK_SHIFT_MASK)
|
|
3467 {
|
|
3468 extend_selection = FALSE;
|
|
3469 gtk_editable_cut_clipboard (editable);
|
|
3470 }
|
|
3471 else
|
|
3472 gtk_text_delete_forward_character (text);
|
|
3473 break;
|
|
3474 case GDK_Tab:
|
|
3475 position = text->point.index;
|
|
3476 gtk_editable_insert_text (editable, "\t", 1, &position);
|
|
3477 break;
|
|
3478 case GDK_Return:
|
|
3479 if (event->state & GDK_CONTROL_MASK)
|
|
3480 gtk_signal_emit_by_name (GTK_OBJECT (text), "activate");
|
|
3481 else
|
|
3482 {
|
|
3483 position = text->point.index;
|
|
3484 gtk_editable_insert_text (editable, "\n", 1, &position);
|
|
3485 }
|
|
3486 break;
|
|
3487 case GDK_Escape:
|
|
3488 /* Don't insert literally */
|
|
3489 return_val = FALSE;
|
|
3490 break;
|
|
3491 #endif
|
|
3492 default:
|
|
3493 return_val = FALSE;
|
|
3494
|
|
3495 #if 0
|
|
3496 if (event->state & GDK_CONTROL_MASK) {
|
|
3497 if ((key >= 'A') && (key <= 'Z'))
|
|
3498 key -= 'A' - 'a';
|
|
3499
|
|
3500 if ((key >= 'a') && (key <= 'z') && control_keys[(int) (key - 'a')])
|
|
3501 {
|
|
3502 (* control_keys[(int) (key - 'a')]) (editable, event->time);
|
|
3503 return_val = TRUE;
|
|
3504 }
|
|
3505
|
|
3506 break;
|
|
3507 }
|
|
3508 else if (event->state & GDK_MOD1_MASK)
|
|
3509 {
|
|
3510 if ((key >= 'A') && (key <= 'Z'))
|
|
3511 key -= 'A' - 'a';
|
|
3512
|
|
3513 if ((key >= 'a') && (key <= 'z') && alt_keys[(int) (key - 'a')])
|
|
3514 {
|
|
3515 (* alt_keys[(int) (key - 'a')]) (editable, event->time);
|
|
3516 return_val = TRUE;
|
|
3517 }
|
|
3518 break;
|
|
3519 }
|
|
3520 #endif
|
|
3521 /*
|
|
3522 if (event->length > 0) {
|
|
3523 html->cursor_pos++;
|
|
3524 gtk_editable_insert_text (editable, event->string, event->length, &position);
|
|
3525
|
|
3526 return_val = TRUE;
|
|
3527 }
|
|
3528 else
|
|
3529 return_val = FALSE;
|
|
3530 */
|
|
3531 }
|
|
3532
|
|
3533 }
|
|
3534
|
|
3535 return return_val;
|
|
3536 }
|
|
3537
|
|
3538 void
|
|
3539 gtk_html_freeze (GtkHtml *html)
|
|
3540 {
|
|
3541 g_return_if_fail (html != NULL);
|
|
3542 g_return_if_fail (GTK_IS_HTML (html));
|
|
3543
|
|
3544 html->frozen++;
|
|
3545 }
|
|
3546
|
|
3547 void
|
|
3548 gtk_html_thaw (GtkHtml *html)
|
|
3549 {
|
|
3550 GdkRectangle area;
|
|
3551
|
|
3552 g_return_if_fail (html != NULL);
|
|
3553 g_return_if_fail (GTK_IS_HTML (html));
|
|
3554
|
|
3555 html->frozen--;
|
|
3556
|
|
3557 if (html->frozen < 0)
|
|
3558 html->frozen = 0;
|
|
3559
|
|
3560 if (html->frozen == 0) {
|
|
3561 if (html->html_area) {
|
|
3562 gint width, height;
|
|
3563 area.x = 0;
|
|
3564 area.y = 0;
|
|
3565
|
|
3566 gdk_window_get_size(html->html_area, &width, &height);
|
|
3567
|
|
3568 area.width = width;
|
|
3569 area.height = height;
|
|
3570
|
|
3571 expose_html(html, &area, TRUE);
|
|
3572 }
|
|
3573 }
|
|
3574 }
|