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