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