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 {
|
|
1513 if (html->tooltip_hb != hb)
|
|
1514 {
|
1
|
1515 html->tooltip_hb = hb;
|
|
1516 if (html->tooltip_timer != -1)
|
|
1517 gtk_timeout_remove(html->tooltip_timer);
|
12
|
1518 if (html->tooltip_window)
|
|
1519 {
|
1
|
1520 gtk_widget_destroy(html->tooltip_window);
|
|
1521 html->tooltip_window = NULL;
|
|
1522 }
|
12
|
1523 html->tooltip_timer =
|
|
1524 gtk_timeout_add(HTML_TOOLTIP_DELAY,
|
|
1525 gtk_html_tooltip_timeout, html);
|
1
|
1526 }
|
12
|
1527 gdk_window_set_cursor(html->html_area,
|
|
1528 gdk_cursor_new(GDK_HAND2));
|
1
|
1529 return TRUE;
|
|
1530 }
|
12
|
1531 urls = urls->next;
|
1
|
1532 }
|
|
1533 if (html->tooltip_timer != -1)
|
|
1534 gtk_timeout_remove(html->tooltip_timer);
|
12
|
1535 if (html->tooltip_window)
|
|
1536 {
|
1
|
1537 gtk_widget_destroy(html->tooltip_window);
|
|
1538 html->tooltip_window = NULL;
|
|
1539 }
|
12
|
1540
|
|
1541
|
|
1542 html->tooltip_hb = NULL;
|
1
|
1543 gdk_window_set_cursor(html->html_area, NULL);
|
|
1544
|
|
1545
|
|
1546 }
|
|
1547
|
|
1548 return TRUE;
|
|
1549 }
|
|
1550
|
12
|
1551 static gint gtk_html_button_release(GtkWidget * widget, GdkEventButton * event)
|
1
|
1552 {
|
12
|
1553 GtkHtml *html;
|
|
1554
|
|
1555 html = GTK_HTML(widget);
|
|
1556
|
|
1557 if (html->frozen > 0)
|
|
1558 return TRUE;
|
|
1559
|
|
1560 if (event->button == 1)
|
|
1561 {
|
|
1562 int realx,
|
|
1563 realy;
|
|
1564 GtkHtmlBit *hb;
|
|
1565 GList *urls = html->urls;
|
|
1566
|
|
1567 realx = event->x;
|
|
1568 realy = event->y + html->yoffset;
|
|
1569 if (realx != html->start_sel_x || realy != html->start_sel_y)
|
|
1570 {
|
|
1571 if (gtk_selection_owner_set(widget,
|
|
1572 GDK_SELECTION_PRIMARY, event->time))
|
|
1573 {
|
|
1574 }
|
|
1575 else
|
|
1576 {
|
|
1577 }
|
|
1578 }
|
|
1579 else
|
|
1580 {
|
|
1581 if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) ==
|
|
1582 widget->window)
|
1
|
1583 gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY,
|
12
|
1584 event->time);
|
|
1585
|
|
1586
|
|
1587 while (urls)
|
|
1588 {
|
|
1589 void open_url_nw(GtkWidget * w, char *url);
|
|
1590 hb = (GtkHtmlBit *) urls->data;
|
1
|
1591 if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
12
|
1592 (realy < hb->y && realy > (hb->y - hb->height)))
|
|
1593 {
|
|
1594 open_url_nw(NULL, hb->url);
|
|
1595 // else
|
|
1596 // open_url(NULL, hb->url);
|
1
|
1597 break;
|
|
1598 }
|
|
1599 urls = urls->next;
|
|
1600 }
|
|
1601 }
|
|
1602 }
|
|
1603 return TRUE;
|
|
1604 }
|
|
1605
|
|
1606
|
|
1607
|
12
|
1608 static gint gtk_html_button_press(GtkWidget * widget, GdkEventButton * event)
|
1
|
1609 {
|
12
|
1610 GtkHtml *html;
|
|
1611 gfloat value;
|
|
1612
|
|
1613
|
|
1614 html = GTK_HTML(widget);
|
|
1615 value = html->vadj->value;
|
|
1616
|
|
1617 if (html->frozen > 0)
|
|
1618 return TRUE;
|
|
1619
|
|
1620 if (event->button == 4)
|
|
1621 {
|
1
|
1622 value -= html->vadj->step_increment;
|
|
1623 if (value < html->vadj->lower)
|
|
1624 value = html->vadj->lower;
|
12
|
1625 gtk_adjustment_set_value(html->vadj, value);
|
|
1626 }
|
|
1627 else if (event->button == 5)
|
|
1628 {
|
1
|
1629 value += html->vadj->step_increment;
|
|
1630 if (value > html->vadj->upper)
|
|
1631 value = html->vadj->upper;
|
12
|
1632 gtk_adjustment_set_value(html->vadj, value);
|
|
1633
|
|
1634 }
|
|
1635 else if (event->button == 1)
|
|
1636 {
|
|
1637 GList *hbits = g_list_last(html->html_bits);
|
|
1638 int realx,
|
|
1639 realy;
|
1
|
1640 GtkHtmlBit *hb;
|
|
1641
|
|
1642 realx = event->x;
|
|
1643 realy = event->y + html->yoffset;
|
|
1644
|
|
1645 html->start_sel_x = realx;
|
|
1646 html->start_sel_y = realy;
|
|
1647
|
|
1648 if (!hbits)
|
|
1649 return TRUE;
|
|
1650
|
12
|
1651 if (html->selected_text)
|
|
1652 {
|
1
|
1653 g_free(html->selected_text);
|
|
1654 html->selected_text = NULL;
|
|
1655 html->start_sel = NULL;
|
|
1656 html->end_sel = NULL;
|
|
1657 html->num_start = 0;
|
|
1658 html->num_end = 0;
|
12
|
1659 while (hbits)
|
|
1660 {
|
|
1661 hb = (GtkHtmlBit *) hbits->data;
|
1
|
1662 if (hb->was_selected)
|
|
1663 gtk_html_draw_bit(html, hb, 1);
|
|
1664 hbits = hbits->prev;
|
|
1665 }
|
|
1666 hbits = g_list_last(html->html_bits);
|
|
1667 }
|
|
1668
|
12
|
1669 hb = (GtkHtmlBit *) hbits->data;
|
|
1670 if (realy > hb->y)
|
|
1671 {
|
1
|
1672 if (hb->text)
|
|
1673 html->num_start = strlen(hb->text) - 1;
|
|
1674 else
|
12
|
1675 html->num_start = 0;
|
1
|
1676 html->start_sel = hb;
|
12
|
1677 }
|
|
1678 else
|
|
1679 while (hbits)
|
|
1680 {
|
|
1681 hb = (GtkHtmlBit *) hbits->data;
|
|
1682 if ((realy < hb->y && realy > (hb->y - hb->height)) &&
|
|
1683 (realx > hb->x + hb->width))
|
|
1684 {
|
|
1685 if (hb->type != HTML_BIT_TEXT)
|
|
1686 {
|
|
1687 html->num_end = 0;
|
|
1688 html->end_sel = hb;
|
|
1689 break;
|
|
1690 }
|
|
1691
|
|
1692 if (hb->text)
|
|
1693 html->num_start = strlen(hb->text) - 1;
|
|
1694 else
|
|
1695 html->num_start = 0;
|
|
1696
|
|
1697 html->start_sel = hb;
|
1
|
1698 break;
|
|
1699 }
|
12
|
1700 else if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
|
1701 (realy < hb->y && realy > (hb->y - hb->height)))
|
|
1702 {
|
|
1703 int i,
|
|
1704 len;
|
|
1705 int w = realx - hb->x;
|
|
1706
|
|
1707 if (hb->type != HTML_BIT_TEXT)
|
|
1708 {
|
|
1709 html->num_end = 0;
|
|
1710 html->end_sel = hb;
|
|
1711 break;
|
|
1712 }
|
|
1713
|
|
1714 if (hb->text)
|
|
1715 len = strlen(hb->text);
|
|
1716 else
|
|
1717 len = 0;
|
|
1718
|
|
1719 for (i = 1; i <= len; i++)
|
|
1720 {
|
|
1721 if (gdk_text_measure(hb->font, hb->text, i) > w)
|
|
1722 {
|
|
1723 html->num_start = i - 1;
|
|
1724 html->start_sel = hb;
|
|
1725 break;
|
|
1726 }
|
|
1727 }
|
1
|
1728 break;
|
|
1729 }
|
12
|
1730 hbits = hbits->prev;
|
1
|
1731 }
|
12
|
1732 }
|
|
1733 else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
|
|
1734 {
|
1
|
1735 GtkHtmlBit *hb = NULL;
|
12
|
1736 int realx,
|
|
1737 realy;
|
|
1738 GList *urls;
|
|
1739
|
1
|
1740 realx = event->x;
|
|
1741 realy = event->y + html->yoffset;
|
12
|
1742
|
1
|
1743 urls = html->urls;
|
12
|
1744 while (urls)
|
|
1745 {
|
|
1746 hb = (GtkHtmlBit *) urls->data;
|
1
|
1747 if ((realx > hb->x && realx < (hb->x + hb->width)) &&
|
12
|
1748 (realy < hb->y && realy > (hb->y - hb->height)))
|
|
1749 {
|
1
|
1750 break;
|
|
1751 }
|
12
|
1752 urls = urls->next;
|
1
|
1753 hb = NULL;
|
|
1754 }
|
12
|
1755
|
|
1756 if (hb != NULL)
|
|
1757 {
|
|
1758 /*
|
|
1759 * GtkWidget *menu, *button;
|
|
1760 *
|
|
1761 * menu = gtk_menu_new();
|
|
1762 *
|
|
1763 * if (web_browser == BROWSER_NETSCAPE) {
|
|
1764 *
|
|
1765 * button = gtk_menu_item_new_with_label("Open URL in existing window");
|
|
1766 * gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1767 * GTK_SIGNAL_FUNC(open_url), hb->url);
|
|
1768 * gtk_menu_append(GTK_MENU(menu), button);
|
|
1769 * gtk_widget_show(button);
|
|
1770 *
|
|
1771 * }
|
|
1772 *
|
|
1773 *
|
|
1774 * button = gtk_menu_item_new_with_label("Open URL in new window");
|
|
1775 * gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1776 * GTK_SIGNAL_FUNC(open_url_nw), hb->url);
|
|
1777 * gtk_menu_append(GTK_MENU(menu), button);
|
|
1778 * gtk_widget_show(button);
|
|
1779 *
|
|
1780 * if (web_browser == BROWSER_NETSCAPE) {
|
|
1781 *
|
|
1782 * button = gtk_menu_item_new_with_label("Add URL as bookmark");
|
|
1783 * gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
1784 * GTK_SIGNAL_FUNC(add_bookmark), hb->url);
|
|
1785 * gtk_menu_append(GTK_MENU(menu), button);
|
|
1786 * gtk_widget_show(button);
|
|
1787 *
|
|
1788 * }
|
|
1789 *
|
|
1790 * gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
|
|
1791 * event->button, event->time);
|
|
1792 */
|
|
1793 }
|
1
|
1794 }
|
12
|
1795
|
1
|
1796 return TRUE;
|
|
1797 }
|
|
1798
|
|
1799
|
12
|
1800 static void gtk_html_draw_bit(GtkHtml * html, GtkHtmlBit * hb, int redraw)
|
1
|
1801 {
|
12
|
1802 int mypos,
|
|
1803 epos,
|
|
1804 spos;
|
|
1805 GdkGC *gc = html->gc;
|
1
|
1806 int shift;
|
12
|
1807 GtkStateType selected_state;
|
|
1808 GtkWidget *widget = GTK_WIDGET(html);
|
1
|
1809 GdkRectangle area;
|
|
1810
|
|
1811 if (html->frozen > 0)
|
|
1812 return;
|
|
1813
|
12
|
1814 if (hb->type == HTML_BIT_TEXT)
|
|
1815 {
|
1
|
1816
|
|
1817 if (!strlen(hb->text))
|
|
1818 return;
|
12
|
1819
|
1
|
1820 mypos = g_list_index(html->html_bits, hb);
|
|
1821 epos = g_list_index(html->html_bits, html->end_sel);
|
|
1822 spos = g_list_index(html->html_bits, html->start_sel);
|
|
1823
|
12
|
1824 if (((html->end_sel == NULL) || (html->start_sel == NULL)) ||
|
|
1825 ((epos < mypos) && (spos < mypos)) ||
|
|
1826 ((epos > mypos) && (spos > mypos)))
|
|
1827 {
|
|
1828 selected_state = GTK_STATE_NORMAL;
|
|
1829 }
|
|
1830 else
|
|
1831 {
|
1
|
1832 selected_state = GTK_STATE_SELECTED;
|
|
1833 }
|
|
1834
|
|
1835
|
|
1836 gdk_text_extents(hb->font, hb->text, 1, &shift, NULL, NULL, NULL, NULL);
|
|
1837
|
12
|
1838 if (selected_state == GTK_STATE_SELECTED)
|
|
1839 {
|
|
1840 int schar = 0,
|
|
1841 echar = 0;
|
|
1842 int startx = 0,
|
|
1843 xwidth = 0;
|
|
1844
|
|
1845 if (epos > spos ||
|
|
1846 (epos == spos && html->num_end >= html->num_start))
|
|
1847 {
|
|
1848 if (mypos == epos)
|
|
1849 {
|
1
|
1850 echar = html->num_end;
|
12
|
1851 xwidth =
|
|
1852 gdk_text_width(hb->font, hb->text, html->num_end + 1);
|
|
1853 }
|
|
1854 else
|
|
1855 {
|
1
|
1856 echar = strlen(hb->text);
|
|
1857 xwidth = hb->width;
|
|
1858 }
|
12
|
1859 if (mypos == spos)
|
|
1860 {
|
1
|
1861 schar = html->num_start;
|
12
|
1862 startx =
|
|
1863 gdk_text_width(hb->font, hb->text, html->num_start);
|
1
|
1864 xwidth -= startx;
|
|
1865 }
|
12
|
1866 }
|
|
1867 else
|
|
1868 {
|
|
1869 if (mypos == spos)
|
|
1870 {
|
1
|
1871 echar = html->num_start;
|
12
|
1872 xwidth =
|
|
1873 gdk_text_width(hb->font, hb->text,
|
|
1874 html->num_start + 1);
|
|
1875 }
|
|
1876 else
|
|
1877 {
|
1
|
1878 echar = strlen(hb->text);
|
|
1879 xwidth = hb->width;
|
|
1880 }
|
12
|
1881 if (mypos == epos)
|
|
1882 {
|
1
|
1883 schar = html->num_end;
|
12
|
1884 startx =
|
|
1885 gdk_text_width(hb->font, hb->text, html->num_end);
|
1
|
1886 xwidth -= startx;
|
|
1887 }
|
|
1888 }
|
|
1889
|
|
1890 if (!redraw && echar == hb->sel_e && schar == hb->sel_s)
|
|
1891 return;
|
12
|
1892
|
1
|
1893 hb->sel_e = echar;
|
|
1894 hb->sel_s = schar;
|
12
|
1895
|
1
|
1896 startx += hb->x;
|
|
1897
|
|
1898
|
12
|
1899 area.x = hb->x - html->xoffset;
|
|
1900 area.y = hb->y - hb->height + 3 - html->yoffset;
|
|
1901 area.width = hb->width + 2;
|
|
1902 area.height = hb->height;
|
|
1903 clear_area(html, &area);
|
|
1904
|
|
1905 gtk_paint_flat_box(widget->style, html->html_area,
|
|
1906 selected_state, GTK_SHADOW_NONE,
|
|
1907 NULL, widget, "text",
|
|
1908 startx,
|
|
1909 hb->y - hb->height + 3 - html->yoffset,
|
|
1910 xwidth + 2, hb->height);
|
|
1911 hb->was_selected = 1;
|
|
1912 }
|
|
1913 else if (hb->was_selected)
|
|
1914 {
|
|
1915 area.x = hb->x - html->xoffset;
|
|
1916 area.y = hb->y - hb->height + 3 - html->yoffset;
|
|
1917 area.width = hb->width + 2;
|
|
1918 area.height = hb->height;
|
|
1919 clear_area(html, &area);
|
|
1920
|
|
1921 hb->sel_e = -1;
|
|
1922 hb->sel_s = -1;
|
|
1923
|
1
|
1924 hb->was_selected = 0;
|
|
1925 }
|
12
|
1926
|
|
1927
|
|
1928
|
|
1929
|
|
1930 if (selected_state == GTK_STATE_SELECTED && (mypos == epos
|
|
1931 || mypos == spos))
|
|
1932 {
|
1
|
1933 char *s = hb->text;
|
12
|
1934 int num = 0,
|
|
1935 width = 0,
|
|
1936 fsel = 0,
|
|
1937 esel = strlen(hb->text);
|
|
1938 int lbearing,
|
|
1939 rbearing,
|
|
1940 w;
|
|
1941
|
|
1942 if (epos > spos ||
|
|
1943 (epos == spos && html->num_end >= html->num_start))
|
|
1944 {
|
1
|
1945 if (mypos == epos)
|
|
1946 esel = html->num_end;
|
|
1947 if (mypos == spos)
|
|
1948 fsel = html->num_start;
|
12
|
1949 }
|
|
1950 else
|
|
1951 {
|
1
|
1952 if (mypos == spos)
|
|
1953 esel = html->num_start;
|
12
|
1954 if (mypos == epos)
|
|
1955 fsel = html->num_end;
|
1
|
1956 }
|
|
1957
|
12
|
1958 while (*s)
|
|
1959 {
|
1
|
1960
|
|
1961 if (num < fsel || num > esel)
|
|
1962 selected_state = GTK_STATE_NORMAL;
|
|
1963 else
|
|
1964 selected_state = GTK_STATE_SELECTED;
|
|
1965 if (hb->fore != NULL)
|
|
1966 gdk_gc_set_foreground(gc, hb->fore);
|
|
1967 else
|
12
|
1968 gdk_gc_set_foreground(gc,
|
|
1969 &widget->style->fg[selected_state]);
|
1
|
1970 if (hb->back != NULL)
|
|
1971 gdk_gc_set_background(gc, hb->back);
|
|
1972 else
|
12
|
1973 gdk_gc_set_background(gc,
|
|
1974 &widget->style->bg[selected_state]);
|
1
|
1975
|
|
1976
|
|
1977 gdk_gc_set_font(gc, hb->font);
|
|
1978
|
12
|
1979 gdk_text_extents(hb->font, s, 1, &lbearing, &rbearing, &w, NULL,
|
|
1980 NULL);
|
|
1981
|
|
1982 gdk_draw_text(html->html_area, hb->font, gc,
|
|
1983 shift + hb->x + width, hb->y - html->yoffset, s,
|
|
1984 1);
|
|
1985
|
|
1986 if (hb->uline)
|
|
1987 gdk_draw_line(html->html_area, gc, shift + hb->x + width,
|
|
1988 hb->y - html->yoffset,
|
|
1989 shift + hb->x + width + w,
|
|
1990 hb->y - html->yoffset);
|
1
|
1991
|
|
1992 if (hb->strike)
|
12
|
1993 gdk_draw_line(html->html_area, gc, shift + hb->x + width,
|
|
1994 hb->y - html->yoffset - (hb->height / 3),
|
|
1995 shift + hb->x + width + w,
|
|
1996 hb->y - html->yoffset - (hb->height / 3));
|
1
|
1997
|
|
1998 width += w;
|
12
|
1999
|
1
|
2000 s++;
|
|
2001 num++;
|
|
2002 }
|
|
2003
|
|
2004
|
12
|
2005 }
|
|
2006 else
|
|
2007 {
|
|
2008 /*my stuff here*/
|
|
2009
|
|
2010 if(!hb->was_selected)
|
|
2011 {
|
|
2012 area.x = hb->x - html->xoffset;
|
|
2013 area.y = hb->y - hb->height + 3 - html->yoffset;
|
|
2014 area.width = hb->width + 2;
|
|
2015 area.height = hb->height;
|
|
2016 clear_area(html, &area);
|
|
2017 }
|
|
2018
|
|
2019 /*end my stuff*/
|
|
2020
|
1
|
2021
|
|
2022 if (hb->fore != NULL)
|
|
2023 gdk_gc_set_foreground(gc, hb->fore);
|
|
2024 else
|
12
|
2025 gdk_gc_set_foreground(gc, &widget->style->fg[selected_state]);
|
1
|
2026 if (hb->back != NULL)
|
|
2027 gdk_gc_set_background(gc, hb->back);
|
|
2028 else
|
|
2029 gdk_gc_set_background(gc, &widget->style->bg[selected_state]);
|
|
2030
|
|
2031
|
|
2032 gdk_gc_set_font(gc, hb->font);
|
|
2033
|
12
|
2034
|
|
2035 gdk_draw_string(html->html_area, hb->font, gc, shift + hb->x,
|
|
2036 hb->y - html->yoffset, hb->text);
|
1
|
2037 if (hb->uline)
|
12
|
2038 gdk_draw_line(html->html_area, gc, shift + hb->x,
|
|
2039 hb->y - html->yoffset,
|
|
2040 hb->x + gdk_string_measure(hb->font, hb->text),
|
|
2041 hb->y - html->yoffset);
|
1
|
2042
|
|
2043 if (hb->strike)
|
12
|
2044 gdk_draw_line(html->html_area, gc, shift + hb->x,
|
|
2045 hb->y - html->yoffset - (hb->height / 3),
|
|
2046 hb->x + gdk_string_measure(hb->font, hb->text),
|
|
2047 hb->y - html->yoffset - (hb->height / 3));
|
1
|
2048
|
|
2049 }
|
12
|
2050 }
|
|
2051 else if (hb->type == HTML_BIT_SEP)
|
|
2052 {
|
|
2053
|
|
2054 gdk_draw_line(html->html_area, gc, hb->x + 2,
|
|
2055 hb->y - html->yoffset - (hb->height / 2 - 1),
|
|
2056 hb->x + hb->width,
|
|
2057 hb->y - html->yoffset - (hb->height / 2 - 1));
|
|
2058
|
|
2059 }
|
|
2060 else if (hb->type == HTML_BIT_PIXMAP)
|
|
2061 {
|
1
|
2062 gdk_gc_set_background(gc, &widget->style->base[GTK_STATE_NORMAL]);
|
12
|
2063 gdk_draw_pixmap(html->html_area, gc, hb->pm, 0, 0, hb->x,
|
|
2064 hb->y - html->yoffset - (hb->height) + 4, hb->width,
|
|
2065 hb->height - 2);
|
1
|
2066 }
|
|
2067 }
|
|
2068
|
|
2069
|
|
2070
|
12
|
2071 gint compare_types(GtkHtmlBit * hb, GtkHtmlBit * hb2)
|
1
|
2072 {
|
12
|
2073 /*
|
|
2074 * In this function, it's OK to accidently return a
|
|
2075 * * 0, but will cause problems on an accidental 1
|
|
2076 */
|
1
|
2077
|
|
2078 if (!hb || !hb2)
|
|
2079 return 0;
|
12
|
2080
|
|
2081
|
1
|
2082 if (hb->uline != hb2->uline)
|
|
2083 return 0;
|
|
2084 if (hb->strike != hb2->strike)
|
12
|
2085 return 0;
|
|
2086 if (hb->font && hb2->font)
|
|
2087 {
|
1
|
2088 if (!gdk_font_equal(hb->font, hb2->font))
|
|
2089 return 0;
|
12
|
2090 }
|
|
2091 else if (hb->font && !hb2->font)
|
|
2092 {
|
1
|
2093 return 0;
|
12
|
2094 }
|
|
2095 else if (!hb->font && hb2->font)
|
|
2096 {
|
1
|
2097 return 0;
|
|
2098 }
|
|
2099 if (hb->type != hb2->type)
|
|
2100 return 0;
|
12
|
2101
|
|
2102 if (hb->fore && hb2->fore)
|
|
2103 {
|
1
|
2104 if (!gdk_color_equal(hb->fore, hb2->fore))
|
|
2105 return 0;
|
12
|
2106 }
|
|
2107 else if (hb->fore && !hb2->fore)
|
|
2108 {
|
1
|
2109 return 0;
|
12
|
2110 }
|
|
2111 else if (!hb->fore && hb2->fore)
|
|
2112 {
|
1
|
2113 return 0;
|
|
2114 }
|
|
2115
|
12
|
2116 if (hb->back && hb2->back)
|
|
2117 {
|
1
|
2118 if (!gdk_color_equal(hb->back, hb2->back))
|
|
2119 return 0;
|
12
|
2120 }
|
|
2121 else if (hb->back && !hb2->back)
|
|
2122 {
|
1
|
2123 return 0;
|
12
|
2124 }
|
|
2125 else if (!hb->back && hb2->back)
|
|
2126 {
|
1
|
2127 return 0;
|
|
2128 }
|
|
2129
|
|
2130 if ((hb->url != NULL && hb2->url == NULL) ||
|
12
|
2131 (hb->url == NULL && hb2->url != NULL))
|
1
|
2132 return 0;
|
12
|
2133
|
|
2134 if (hb->url != NULL && hb2->url != NULL)
|
1
|
2135 if (strcasecmp(hb->url, hb2->url))
|
|
2136 return 0;
|
12
|
2137
|
1
|
2138 return 1;
|
|
2139 }
|
|
2140
|
12
|
2141 static gint html_bit_is_onscreen(GtkHtml * html, GtkHtmlBit * hb)
|
1
|
2142 {
|
12
|
2143 gint width,
|
|
2144 height;
|
1
|
2145
|
|
2146 gdk_window_get_size(html->html_area, &width, &height);
|
12
|
2147
|
|
2148 if (hb->y < html->yoffset)
|
|
2149 {
|
1
|
2150 return 0;
|
|
2151 }
|
|
2152
|
12
|
2153 if ((hb->y - hb->height) > (html->yoffset + height))
|
|
2154 {
|
1
|
2155 return 0;
|
|
2156 }
|
|
2157 return 1;
|
|
2158 }
|
|
2159
|
12
|
2160 static void draw_cursor(GtkHtml * html)
|
1
|
2161 {
|
12
|
2162 if (html->editable &&
|
|
2163 html->cursor_hb &&
|
|
2164 GTK_WIDGET_DRAWABLE(html) &&
|
|
2165 html_bit_is_onscreen(html, html->cursor_hb))
|
|
2166 {
|
|
2167 gint x,
|
|
2168 y;
|
1
|
2169 gint width;
|
|
2170
|
|
2171 GdkFont *font = html->cursor_hb->font;
|
|
2172
|
12
|
2173 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL,
|
|
2174 NULL, &width, NULL, NULL);
|
|
2175
|
|
2176 gdk_gc_set_foreground(html->gc,
|
|
2177 >K_WIDGET(html)->style->text[GTK_STATE_NORMAL]);
|
1
|
2178
|
|
2179 y = html->cursor_hb->y - html->yoffset;
|
|
2180 x = html->cursor_hb->x + width;
|
|
2181
|
|
2182
|
12
|
2183 gdk_draw_line(html->html_area, html->gc, x, y, x, y - font->ascent);
|
1
|
2184
|
|
2185 }
|
|
2186 }
|
|
2187
|
12
|
2188 static void undraw_cursor(GtkHtml * html)
|
1
|
2189 {
|
12
|
2190 if (html->editable &&
|
|
2191 html->cursor_hb &&
|
|
2192 GTK_WIDGET_DRAWABLE(html) &&
|
|
2193 html_bit_is_onscreen(html, html->cursor_hb))
|
|
2194 {
|
|
2195 gint x,
|
|
2196 y;
|
1
|
2197 gint width;
|
12
|
2198 GdkRectangle area;
|
|
2199
|
1
|
2200 GdkFont *font = html->cursor_hb->font;
|
|
2201
|
12
|
2202 gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL,
|
|
2203 NULL, &width, NULL, NULL);
|
1
|
2204
|
|
2205 y = html->cursor_hb->y - html->yoffset;
|
|
2206 x = html->cursor_hb->x + width;
|
|
2207
|
|
2208 area.x = x;
|
|
2209 area.y = y - font->ascent;
|
|
2210 area.height = font->ascent + 1;
|
|
2211 area.width = 1;
|
|
2212
|
|
2213
|
12
|
2214 clear_area(html, &area);
|
1
|
2215
|
|
2216 gtk_html_draw_bit(html, html->cursor_hb, 1);
|
12
|
2217
|
|
2218
|
|
2219 }
|
1
|
2220 }
|
|
2221
|
|
2222
|
12
|
2223 static void expose_html(GtkHtml * html, GdkRectangle * area, gboolean cursor)
|
1
|
2224 {
|
12
|
2225 GList *hbits;
|
|
2226 GtkHtmlBit *hb;
|
|
2227 gint width,
|
|
2228 height;
|
|
2229 gint realy;
|
|
2230
|
|
2231
|
|
2232 if (html->frozen > 0)
|
|
2233 return;
|
|
2234
|
|
2235
|
|
2236 hbits = html->html_bits;
|
1
|
2237
|
|
2238 gdk_window_get_size(html->html_area, &width, &height);
|
|
2239
|
12
|
2240 realy = area->y + html->yoffset;
|
|
2241
|
|
2242 clear_area(html, area);
|
|
2243
|
|
2244 while (hbits)
|
|
2245 {
|
|
2246
|
|
2247 hb = (GtkHtmlBit *) hbits->data;
|
1
|
2248
|
|
2249 if (html_bit_is_onscreen(html, hb))
|
12
|
2250 gtk_html_draw_bit(html, hb, 1);
|
|
2251
|
|
2252
|
|
2253 hbits = hbits->next;
|
|
2254 }
|
1
|
2255 }
|
|
2256
|
12
|
2257 static void resize_html(GtkHtml * html)
|
1
|
2258 {
|
|
2259 GList *hbits = html->html_bits;
|
|
2260 GList *html_bits = html->html_bits;
|
12
|
2261 GtkHtmlBit *hb,
|
|
2262 *hb2;
|
1
|
2263 char *str;
|
|
2264 gint height;
|
|
2265
|
12
|
2266 if (!hbits)
|
|
2267 return;
|
|
2268
|
|
2269
|
|
2270 html->html_bits = NULL;
|
|
2271
|
|
2272 html->current_x = 0;
|
1
|
2273 html->current_y = 0;
|
|
2274
|
12
|
2275 html->vadj->upper = 0;
|
|
2276
|
|
2277 gtk_html_freeze(html);
|
|
2278
|
|
2279 while (hbits)
|
|
2280 {
|
|
2281 hb = (GtkHtmlBit *) hbits->data;
|
|
2282 if (hb->type == HTML_BIT_SEP)
|
|
2283 {
|
|
2284
|
1
|
2285 gtk_html_add_seperator(html);
|
|
2286
|
|
2287 g_free(hb);
|
|
2288
|
|
2289 hbits = hbits->next;
|
|
2290 continue;
|
|
2291 }
|
12
|
2292 if (hb->type == HTML_BIT_PIXMAP)
|
|
2293 {
|
1
|
2294
|
|
2295 gtk_html_add_pixmap(html, hb->pm, hb->fit);
|
|
2296
|
|
2297 g_free(hb);
|
|
2298
|
|
2299 hbits = hbits->next;
|
|
2300 continue;
|
|
2301 }
|
12
|
2302
|
|
2303 if (hb->newline)
|
|
2304 {
|
1
|
2305 int i;
|
|
2306
|
12
|
2307 if (!hb->text)
|
|
2308 {
|
1
|
2309 hb->text = g_malloc(1);
|
|
2310 hb->text[0] = 0;
|
|
2311 }
|
12
|
2312 for (i = 0; i < hb->newline; i++)
|
|
2313 {
|
|
2314 str = hb->text;
|
1
|
2315 hb->text = g_strconcat(str, "\n", NULL);
|
|
2316 g_free(str);
|
|
2317 }
|
|
2318 }
|
|
2319
|
12
|
2320 if (hbits->next)
|
|
2321 {
|
|
2322 hb2 = (GtkHtmlBit *) hbits->next->data;
|
|
2323 }
|
|
2324 else
|
|
2325 {
|
|
2326 hb2 = NULL;
|
|
2327 }
|
|
2328
|
|
2329
|
|
2330
|
|
2331 if (!hb->newline && compare_types(hb, hb2))
|
|
2332 {
|
1
|
2333 str = hb2->text;
|
|
2334 hb2->text = g_strconcat(hb->text, hb2->text, NULL);
|
|
2335 g_free(str);
|
|
2336 hb2 = NULL;
|
12
|
2337 }
|
|
2338 else if (hb->text)
|
|
2339 {
|
1
|
2340 gtk_html_add_text(html, hb->font, hb->fore, hb->back,
|
12
|
2341 hb->text, strlen(hb->text), hb->uline, hb->strike,
|
|
2342 hb->url);
|
1
|
2343 }
|
|
2344
|
12
|
2345
|
|
2346
|
|
2347 /*
|
|
2348 * Font stays, so do colors (segfaults if I free)
|
|
2349 */
|
1
|
2350 if (hb->fore)
|
|
2351 gdk_color_free(hb->fore);
|
|
2352 if (hb->back)
|
|
2353 gdk_color_free(hb->back);
|
|
2354 if (hb->text)
|
|
2355 g_free(hb->text);
|
|
2356 if (hb->url)
|
|
2357 g_free(hb->url);
|
|
2358
|
12
|
2359 g_free(hb);
|
1
|
2360
|
|
2361 hbits = hbits->next;
|
|
2362 }
|
|
2363
|
12
|
2364 g_list_free(html_bits);
|
|
2365
|
|
2366
|
|
2367 gtk_html_thaw(html);
|
|
2368
|
1
|
2369 gdk_window_get_size(html->html_area, NULL, &height);
|
12
|
2370 gtk_adjustment_set_value(html->vadj, html->vadj->upper - height);
|
1
|
2371
|
|
2372 }
|
|
2373
|
12
|
2374 static GdkGC *create_bg_gc(GtkHtml * html)
|
1
|
2375 {
|
12
|
2376 GdkGCValues values;
|
|
2377
|
|
2378 values.tile = GTK_WIDGET(html)->style->bg_pixmap[GTK_STATE_NORMAL];
|
|
2379 values.fill = GDK_TILED;
|
|
2380
|
|
2381 return gdk_gc_new_with_values(html->html_area, &values,
|
|
2382 GDK_GC_FILL | GDK_GC_TILE);
|
1
|
2383 }
|
|
2384
|
12
|
2385 static void clear_area(GtkHtml * html, GdkRectangle * area)
|
1
|
2386 {
|
12
|
2387 GtkWidget *widget = GTK_WIDGET(html);
|
|
2388 gint x,
|
|
2389 y;
|
|
2390
|
|
2391
|
|
2392 if (html->transparent)
|
|
2393 {
|
1
|
2394 if (html->pm == NULL)
|
|
2395 html->pm = get_desktop_pixmap(widget);
|
|
2396
|
12
|
2397 if (html->pm == NULL)
|
|
2398 return;
|
|
2399
|
|
2400 if (html->bg_gc == NULL)
|
|
2401 {
|
|
2402 GdkGCValues values;
|
|
2403
|
|
2404 values.tile = html->pm;
|
|
2405 values.fill = GDK_TILED;
|
|
2406
|
|
2407 html->bg_gc = gdk_gc_new_with_values(html->html_area, &values,
|
|
2408 GDK_GC_FILL | GDK_GC_TILE);
|
|
2409
|
|
2410 }
|
|
2411
|
1
|
2412 gdk_window_get_deskrelative_origin(html->html_area, &x, &y);
|
|
2413
|
12
|
2414 gdk_draw_pixmap(html->html_area, html->bg_gc, html->pm,
|
|
2415 x + area->x, y + area->y, area->x, area->y, area->width,
|
|
2416 area->height);
|
1
|
2417
|
|
2418 return;
|
|
2419
|
|
2420 }
|
12
|
2421 if (html->bg_gc)
|
|
2422 {
|
|
2423
|
|
2424 gint width,
|
|
2425 height;
|
|
2426
|
|
2427 gdk_window_get_size(widget->style->bg_pixmap[GTK_STATE_NORMAL], &width,
|
|
2428 &height);
|
|
2429
|
|
2430 gdk_gc_set_ts_origin(html->bg_gc,
|
|
2431 (-html->xoffset) % width,
|
|
2432 (-html->yoffset) % height);
|
|
2433
|
|
2434 gdk_draw_rectangle(html->html_area, html->bg_gc, TRUE,
|
|
2435 area->x, area->y, area->width, area->height);
|
|
2436 }
|
|
2437 else
|
|
2438 gdk_window_clear_area(html->html_area, area->x, area->y, area->width,
|
|
2439 area->height);
|
1
|
2440 }
|
|
2441
|
|
2442
|
|
2443
|
|
2444
|
12
|
2445 static void gtk_html_destroy(GtkObject * object)
|
1
|
2446 {
|
12
|
2447 GtkHtml *html;
|
|
2448
|
|
2449 g_return_if_fail(object != NULL);
|
|
2450 g_return_if_fail(GTK_IS_HTML(object));
|
|
2451
|
|
2452 html = (GtkHtml *) object;
|
|
2453
|
|
2454
|
|
2455 gtk_signal_disconnect_by_data(GTK_OBJECT(html->hadj), html);
|
|
2456 gtk_signal_disconnect_by_data(GTK_OBJECT(html->vadj), html);
|
|
2457
|
|
2458 if (html->timer)
|
|
2459 {
|
|
2460 gtk_timeout_remove(html->timer);
|
|
2461 html->timer = 0;
|
1
|
2462 }
|
|
2463
|
12
|
2464 if (html->tooltip_timer)
|
|
2465 {
|
|
2466 gtk_timeout_remove(html->tooltip_timer);
|
1
|
2467 html->tooltip_timer = -1;
|
|
2468 }
|
|
2469
|
12
|
2470
|
|
2471 GTK_OBJECT_CLASS(parent_class)->destroy(object);
|
|
2472
|
1
|
2473 }
|
|
2474
|
12
|
2475 static void gtk_html_finalize(GtkObject * object)
|
1
|
2476 {
|
12
|
2477 GList *hbits;
|
|
2478 GtkHtml *html;
|
1
|
2479 GtkHtmlBit *hb;
|
|
2480
|
|
2481
|
12
|
2482 g_return_if_fail(object != NULL);
|
|
2483 g_return_if_fail(GTK_IS_HTML(object));
|
|
2484
|
|
2485 html = (GtkHtml *) object;
|
|
2486
|
|
2487 gtk_object_unref(GTK_OBJECT(html->hadj));
|
|
2488 gtk_object_unref(GTK_OBJECT(html->vadj));
|
|
2489
|
|
2490 hbits = html->html_bits;
|
|
2491
|
|
2492 while (hbits)
|
|
2493 {
|
|
2494 hb = (GtkHtmlBit *) hbits->data;
|
|
2495 if (hb->fore)
|
|
2496 gdk_color_free(hb->fore);
|
|
2497 if (hb->back)
|
|
2498 gdk_color_free(hb->back);
|
|
2499 if (hb->text)
|
|
2500 g_free(hb->text);
|
|
2501 if (hb->url)
|
|
2502 g_free(hb->url);
|
|
2503 if (hb->pm)
|
|
2504 gdk_pixmap_unref(hb->pm);
|
|
2505
|
|
2506 g_free(hb);
|
|
2507 hbits = hbits->next;
|
|
2508 }
|
|
2509 if (html->html_bits)
|
|
2510 g_list_free(html->html_bits);
|
|
2511
|
|
2512 if (html->urls)
|
|
2513 g_list_free(html->urls);
|
|
2514
|
|
2515 if (html->selected_text)
|
|
2516 g_free(html->selected_text);
|
|
2517
|
|
2518 if (html->gc)
|
|
2519 gdk_gc_destroy(html->gc);
|
|
2520
|
|
2521 if (html->bg_gc)
|
|
2522 gdk_gc_destroy(html->bg_gc);
|
1
|
2523
|
|
2524 if (html->tooltip_window)
|
|
2525 gtk_widget_destroy(html->tooltip_window);
|
12
|
2526
|
|
2527 GTK_OBJECT_CLASS(parent_class)->finalize(object);
|
1
|
2528 }
|
|
2529
|
12
|
2530 static void gtk_html_realize(GtkWidget * widget)
|
1
|
2531 {
|
12
|
2532 GtkHtml *html;
|
|
2533 GdkWindowAttr attributes;
|
|
2534 gint attributes_mask;
|
|
2535
|
|
2536 g_return_if_fail(widget != NULL);
|
|
2537 g_return_if_fail(GTK_IS_HTML(widget));
|
|
2538
|
|
2539 html = GTK_HTML(widget);
|
|
2540 GTK_WIDGET_SET_FLAGS(html, GTK_REALIZED);
|
|
2541
|
|
2542 attributes.window_type = GDK_WINDOW_CHILD;
|
|
2543 attributes.x = widget->allocation.x;
|
|
2544 attributes.y = widget->allocation.y;
|
|
2545 attributes.width = widget->allocation.width;
|
|
2546 attributes.height = widget->allocation.height;
|
|
2547 attributes.wclass = GDK_INPUT_OUTPUT;
|
|
2548 attributes.visual = gtk_widget_get_visual(widget);
|
|
2549 attributes.colormap = gtk_widget_get_colormap(widget);
|
|
2550 attributes.event_mask = gtk_widget_get_events(widget);
|
|
2551 attributes.event_mask |= (GDK_EXPOSURE_MASK |
|
|
2552 GDK_BUTTON_PRESS_MASK |
|
|
2553 GDK_BUTTON_RELEASE_MASK |
|
|
2554 GDK_BUTTON_MOTION_MASK |
|
|
2555 GDK_ENTER_NOTIFY_MASK |
|
|
2556 GDK_LEAVE_NOTIFY_MASK |
|
|
2557 GDK_POINTER_MOTION_MASK |
|
|
2558 GDK_POINTER_MOTION_HINT_MASK |
|
|
2559 GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK);
|
|
2560
|
|
2561 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
|
|
2562
|
|
2563 widget->window =
|
|
2564 gdk_window_new(gtk_widget_get_parent_window(widget), &attributes,
|
|
2565 attributes_mask);
|
|
2566 gdk_window_set_user_data(widget->window, html);
|
|
2567
|
|
2568 attributes.x = (widget->style->klass->xthickness + BORDER_WIDTH);
|
|
2569 attributes.y = (widget->style->klass->ythickness + BORDER_WIDTH);
|
|
2570 attributes.width =
|
|
2571 MAX(1, (gint) widget->allocation.width - (gint) attributes.x * 2);
|
|
2572 attributes.height =
|
|
2573 MAX(1, (gint) widget->allocation.height - (gint) attributes.y * 2);
|
|
2574
|
|
2575 html->html_area =
|
|
2576 gdk_window_new(widget->window, &attributes, attributes_mask);
|
|
2577 gdk_window_set_user_data(html->html_area, html);
|
|
2578
|
|
2579 widget->style = gtk_style_attach(widget->style, widget->window);
|
|
2580
|
|
2581 /*
|
|
2582 * Can't call gtk_style_set_background here because it's handled specially
|
|
2583 */
|
|
2584 gdk_window_set_background(widget->window,
|
|
2585 &widget->style->base[GTK_STATE_NORMAL]);
|
|
2586 gdk_window_set_background(html->html_area,
|
|
2587 &widget->style->base[GTK_STATE_NORMAL]);
|
|
2588
|
|
2589 if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
|
|
2590 html->bg_gc = create_bg_gc(html);
|
|
2591
|
|
2592 html->gc = gdk_gc_new(html->html_area);
|
|
2593 gdk_gc_set_exposures(html->gc, TRUE);
|
|
2594 gdk_gc_set_foreground(html->gc, &widget->style->text[GTK_STATE_NORMAL]);
|
|
2595
|
|
2596 gdk_window_show(html->html_area);
|
1
|
2597
|
|
2598 }
|
|
2599
|
12
|
2600 static void gtk_html_style_set(GtkWidget * widget, GtkStyle * previous_style)
|
1
|
2601 {
|
12
|
2602 GtkHtml *html;
|
|
2603
|
|
2604 g_return_if_fail(widget != NULL);
|
|
2605 g_return_if_fail(GTK_IS_HTML(widget));
|
|
2606
|
|
2607 html = GTK_HTML(widget);
|
|
2608 if (GTK_WIDGET_REALIZED(widget))
|
|
2609 {
|
|
2610 gdk_window_set_background(widget->window,
|
|
2611 &widget->style->base[GTK_STATE_NORMAL]);
|
|
2612 gdk_window_set_background(html->html_area,
|
|
2613 &widget->style->base[GTK_STATE_NORMAL]);
|
|
2614
|
|
2615 if (html->bg_gc)
|
|
2616 {
|
|
2617 gdk_gc_destroy(html->bg_gc);
|
|
2618 html->bg_gc = NULL;
|
|
2619 }
|
|
2620
|
|
2621 if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
|
|
2622 {
|
|
2623 html->bg_gc = create_bg_gc(html);
|
|
2624 }
|
|
2625
|
|
2626 }
|
1
|
2627 }
|
|
2628
|
12
|
2629 static void gtk_html_unrealize(GtkWidget * widget)
|
1
|
2630 {
|
12
|
2631 GtkHtml *html;
|
|
2632
|
|
2633 g_return_if_fail(widget != NULL);
|
|
2634 g_return_if_fail(GTK_IS_HTML(widget));
|
|
2635
|
|
2636 html = GTK_HTML(widget);
|
|
2637
|
|
2638 gdk_window_set_user_data(html->html_area, NULL);
|
|
2639 gdk_window_destroy(html->html_area);
|
|
2640 html->html_area = NULL;
|
|
2641
|
|
2642 gdk_gc_destroy(html->gc);
|
|
2643 html->gc = NULL;
|
|
2644
|
|
2645 if (html->bg_gc)
|
|
2646 {
|
|
2647 gdk_gc_destroy(html->bg_gc);
|
|
2648 html->bg_gc = NULL;
|
|
2649 }
|
|
2650
|
|
2651 if (GTK_WIDGET_CLASS(parent_class)->unrealize)
|
|
2652 (*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget);
|
1
|
2653 }
|
|
2654
|
|
2655
|
|
2656
|
|
2657
|
|
2658
|
12
|
2659 static void gtk_html_add_pixmap(GtkHtml * html, GdkPixmap * pm, int fit)
|
1
|
2660 {
|
12
|
2661 GtkHtmlBit *last_hb;
|
|
2662 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
|
|
2663 GdkWindowPrivate *private = (GdkWindowPrivate *) pm;
|
|
2664
|
|
2665 last_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data;
|
1
|
2666
|
|
2667 hb->fit = fit;
|
|
2668 hb->x = html->current_x;
|
|
2669 hb->y = html->current_y;
|
12
|
2670 if (fit)
|
1
|
2671 hb->height = last_hb->height;
|
|
2672 else
|
|
2673 hb->height = private->height;
|
|
2674 hb->type = HTML_BIT_PIXMAP;
|
|
2675 hb->width = private->width;
|
|
2676 hb->text = NULL;
|
|
2677 hb->url = NULL;
|
|
2678 hb->fore = NULL;
|
|
2679 hb->back = NULL;
|
|
2680 hb->font = NULL;
|
12
|
2681 hb->uline = 0;
|
|
2682 hb->strike = 0;
|
1
|
2683 hb->was_selected = 0;
|
12
|
2684 hb->newline = 0;
|
|
2685 hb->pm = pm;
|
|
2686
|
|
2687 if (html->current_x == BORDER_WIDTH)
|
|
2688 {
|
1
|
2689 html->current_y += hb->height;
|
|
2690 hb->y += hb->height;
|
|
2691 }
|
|
2692
|
|
2693
|
12
|
2694 html->current_x += hb->width;
|
|
2695
|
1
|
2696 gtk_html_draw_bit(html, hb, 1);
|
|
2697
|
|
2698 html->html_bits = g_list_append(html->html_bits, hb);
|
|
2699
|
|
2700
|
|
2701 }
|
|
2702
|
12
|
2703 static void gtk_html_add_seperator(GtkHtml * html)
|
1
|
2704 {
|
12
|
2705 GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
|
|
2706 gint width,
|
|
2707 height;
|
|
2708
|
1
|
2709 html->current_x = 0;
|
|
2710 html->current_y += 5;
|
|
2711
|
12
|
2712 gdk_window_get_size(html->html_area, &width, &height);
|
|
2713
|
1
|
2714 hb->x = html->current_x;
|
|
2715 hb->y = html->current_y;
|
|
2716 hb->height = 5;
|
|
2717 hb->type = HTML_BIT_SEP;
|
12
|
2718 hb->width =
|
|
2719 width -
|
|
2720 GTK_SCROLLED_WINDOW(GTK_WIDGET(html)->parent)->vscrollbar->allocation.
|
|
2721 width - 10;
|
1
|
2722 hb->text = NULL;
|
|
2723 hb->url = NULL;
|
|
2724 hb->fore = NULL;
|
|
2725 hb->back = NULL;
|
|
2726 hb->font = NULL;
|
12
|
2727 hb->uline = 0;
|
|
2728 hb->strike = 0;
|
1
|
2729 hb->was_selected = 0;
|
12
|
2730 hb->newline = 0;
|
|
2731 hb->pm = NULL;
|
1
|
2732
|
|
2733 gtk_html_draw_bit(html, hb, 1);
|
|
2734
|
|
2735 html->html_bits = g_list_append(html->html_bits, hb);
|
|
2736
|
|
2737 }
|
|
2738
|
|
2739
|
12
|
2740 static void gtk_html_add_text(GtkHtml * html,
|
|
2741 GdkFont * cfont,
|
|
2742 GdkColor * fore,
|
|
2743 GdkColor * back,
|
|
2744 char *chars,
|
|
2745 gint length, gint uline, gint strike, char *url)
|
1
|
2746 {
|
12
|
2747 char *nextline = NULL,
|
|
2748 *c,
|
|
2749 *text,
|
|
2750 *tmp;
|
|
2751 GdkGC *gc;
|
|
2752 int nl = 0,
|
|
2753 nl2 = 0;
|
|
2754 int maxwidth;
|
|
2755 gint lb;
|
|
2756 GList *hbits;
|
|
2757 int num = 0,
|
|
2758 i,
|
|
2759 height;
|
|
2760 GtkHtmlBit *hb;
|
|
2761 gint hwidth,
|
|
2762 hheight;
|
|
2763
|
|
2764 if (length == 1 && chars[0] == '\n')
|
|
2765 {
|
|
2766 GtkHtmlBit *h;
|
|
2767 hbits = g_list_last(html->html_bits);
|
|
2768 if (!hbits)
|
|
2769 return;
|
|
2770 /*
|
|
2771 * I realize this loses a \n sometimes
|
|
2772 * * if it's the first thing in the widget.
|
|
2773 * * so fucking what.
|
|
2774 */
|
|
2775
|
|
2776 h = (GtkHtmlBit *) hbits->data;
|
|
2777 h->newline++;
|
|
2778 if (html->current_x > 0)
|
|
2779 html->current_x = 0;
|
|
2780 else
|
|
2781 html->current_y += cfont->ascent + cfont->descent + 2;
|
|
2782 return;
|
|
2783 }
|
|
2784
|
|
2785
|
|
2786
|
|
2787 c = text = g_malloc(length + 2);
|
|
2788 strncpy(text, chars, length);
|
|
2789 text[length] = 0;
|
|
2790
|
|
2791
|
|
2792 gc = html->gc;
|
|
2793
|
|
2794 if (gc == NULL)
|
|
2795 gc = html->gc = gdk_gc_new(html->html_area);
|
|
2796
|
|
2797 gdk_gc_set_font(gc, cfont);
|
|
2798
|
|
2799
|
|
2800 while (*c)
|
|
2801 {
|
|
2802 if (*c == '\n')
|
|
2803 {
|
|
2804 if (*(c + 1) == '\0')
|
|
2805 {
|
|
2806 nl = 1;
|
|
2807 length--;
|
|
2808 c[0] = '\0';
|
|
2809 break;
|
|
2810 }
|
|
2811 if (*c)
|
|
2812 {
|
|
2813 gtk_html_add_text(html, cfont, fore, back, text, num + 1, uline,
|
|
2814 strike, url);
|
|
2815 tmp = text;
|
|
2816 length -= (num + 1);
|
|
2817 text = g_malloc(length + 2);
|
|
2818 strncpy(text, (c + 1), length);
|
|
2819 text[length] = 0;
|
|
2820 c = text;
|
|
2821 num = 0;
|
|
2822 g_free(tmp);
|
1
|
2823 continue;
|
12
|
2824 }
|
|
2825 }
|
|
2826
|
|
2827 num++;
|
|
2828 c++;
|
|
2829 }
|
|
2830
|
|
2831 /*
|
|
2832 * Note, yG is chosen because G is damn high, and y is damn low,
|
|
2833 */
|
|
2834 /*
|
|
2835 * it should be just fine. :)
|
|
2836 */
|
|
2837
|
|
2838 gdk_window_get_size(html->html_area, &hwidth, &hheight);
|
|
2839
|
|
2840 num = strlen(text);
|
|
2841
|
|
2842 while (GTK_WIDGET(html)->allocation.width < 20)
|
|
2843 {
|
|
2844 while (gtk_events_pending())
|
1
|
2845 gtk_main_iteration();
|
|
2846 }
|
|
2847
|
12
|
2848 maxwidth = (hwidth - html->current_x - 8);
|
|
2849 /*
|
|
2850 * HTK_SCROLLED_WINDOW(GTK_WIDGET(layout)->parent)->vscrollbar->allocation.width) - 8;
|
|
2851 */
|
|
2852
|
|
2853 while (gdk_text_measure(cfont, text, num) > maxwidth)
|
|
2854 {
|
|
2855 if (num > 1)
|
|
2856 num--;
|
|
2857 else
|
|
2858 {
|
|
2859
|
|
2860 html->current_x = 0;
|
|
2861 if (nl)
|
|
2862 {
|
1
|
2863 text[length] = '\n';
|
12
|
2864 length++;
|
1
|
2865 }
|
12
|
2866 gtk_html_add_text(html, cfont, fore, back, text, length, uline,
|
|
2867 strike, url);
|
1
|
2868 g_free(text);
|
|
2869 return;
|
|
2870 }
|
|
2871
|
|
2872 }
|
|
2873
|
12
|
2874 height = cfont->ascent + cfont->descent + 2;
|
|
2875
|
|
2876
|
|
2877 if ((int) (html->vadj->upper - html->current_y) < (int) (height * 2))
|
|
2878 {
|
|
2879 int val;
|
|
2880 val = (height * 2) + html->current_y;
|
|
2881 html->vadj->upper = val;
|
|
2882 adjust_adj(html, html->vadj);
|
1
|
2883 }
|
|
2884
|
12
|
2885
|
|
2886 if (html->current_x == 0)
|
|
2887 {
|
|
2888 html->current_y += height;
|
|
2889 gdk_text_extents(cfont, text, 1, &lb, NULL, NULL, NULL, NULL);
|
|
2890 html->current_x += (2 - lb);
|
|
2891 }
|
|
2892 else if ((hbits = g_list_last(html->html_bits)) != NULL)
|
|
2893 {
|
|
2894 int diff,
|
|
2895 y;
|
|
2896 hb = (GtkHtmlBit *) hbits->data;
|
|
2897 if (height > hb->height)
|
|
2898 {
|
1
|
2899 diff = height - hb->height;
|
|
2900 y = hb->y;
|
|
2901 html->current_y += diff;
|
12
|
2902 while (hbits)
|
|
2903 {
|
|
2904 hb = (GtkHtmlBit *) hbits->data;
|
1
|
2905 if (hb->y != y)
|
12
|
2906 break;
|
|
2907 hb->height = height;
|
|
2908 hb->y += diff; ////////////my thing here /////////////////
|
|
2909 gtk_html_draw_bit(html, hb, FALSE);
|
|
2910
|
|
2911 hbits = hbits->prev;
|
1
|
2912 }
|
|
2913 }
|
|
2914 }
|
|
2915
|
|
2916
|
|
2917
|
|
2918
|
12
|
2919 if (num != strlen(text))
|
|
2920 {
|
|
2921 /*
|
|
2922 * This is kinda cheesy but it may make things
|
|
2923 * * much better lookin
|
|
2924 */
|
|
2925 for (i = 2; i < 15; i++)
|
|
2926 {
|
|
2927 if ((num - i) < 0)
|
|
2928 {
|
1
|
2929 html->current_x = 0;
|
12
|
2930 gtk_html_add_text(html, cfont, fore, back, text, strlen(text),
|
|
2931 uline, strike, url);
|
|
2932 return;
|
|
2933 }
|
|
2934 else if (text[num - i] == ' ')
|
|
2935 {
|
|
2936 num = num - (i - 1);
|
1
|
2937 nl2 = 1;
|
|
2938 break;
|
|
2939 }
|
|
2940 }
|
|
2941
|
|
2942 nextline = g_malloc(length - num + 2);
|
12
|
2943 strncpy(nextline, (char *) (text + num), length - num);
|
1
|
2944 nextline[length - num] = 0;
|
12
|
2945 if (nl)
|
|
2946 {
|
1
|
2947 nextline[length - num] = '\n';
|
|
2948 nextline[length - num + 1] = 0;
|
|
2949 nl = 0;
|
|
2950 }
|
|
2951
|
|
2952
|
|
2953 text[num] = 0;
|
|
2954 }
|
|
2955
|
|
2956
|
|
2957 if (url != NULL)
|
|
2958 fore = get_color(3355647, gdk_window_get_colormap(html->html_area));
|
|
2959
|
|
2960
|
|
2961 hb = g_new0(GtkHtmlBit, 1);
|
|
2962
|
|
2963 hb->text = g_strdup(text);
|
|
2964
|
12
|
2965 if (fore)
|
1
|
2966 hb->fore = gdk_color_copy(fore);
|
|
2967 else
|
|
2968 hb->fore = NULL;
|
|
2969
|
|
2970 if (back)
|
|
2971 hb->back = gdk_color_copy(back);
|
|
2972 else
|
|
2973 hb->back = NULL;
|
|
2974 hb->font = cfont;
|
|
2975 hb->uline = uline;
|
|
2976 hb->strike = strike;
|
|
2977 hb->height = height;
|
|
2978 gdk_text_extents(cfont, text, num, &lb, NULL, &hb->width, NULL, NULL);
|
|
2979 hb->x = html->current_x;
|
|
2980 hb->y = html->current_y;
|
12
|
2981 hb->type = HTML_BIT_TEXT;
|
|
2982 hb->pm = NULL;
|
|
2983 if (url != NULL)
|
|
2984 {
|
1
|
2985 uline = 1;
|
|
2986 hb->uline = 1;
|
|
2987 hb->url = g_strdup(url);
|
12
|
2988 }
|
|
2989 else
|
|
2990 {
|
1
|
2991 hb->url = NULL;
|
|
2992 }
|
|
2993 html->current_x += hb->width;
|
|
2994
|
|
2995 html->html_bits = g_list_append(html->html_bits, hb);
|
12
|
2996 if (url != NULL)
|
|
2997 {
|
|
2998 html->urls = g_list_append(html->urls, hb);
|
|
2999 }
|
|
3000
|
|
3001
|
|
3002
|
|
3003 gtk_html_draw_bit(html, hb, 1);
|
|
3004
|
|
3005 if (nl || nl2)
|
|
3006 {
|
|
3007 if (nl)
|
|
3008 hb->newline = 1;
|
|
3009 html->current_x = 0;
|
|
3010 }
|
|
3011 else
|
|
3012 hb->newline = 0;
|
|
3013
|
|
3014
|
|
3015 if (nextline != NULL)
|
|
3016 {
|
|
3017 gtk_html_add_text(html, cfont, fore, back, nextline, strlen(nextline),
|
|
3018 uline, strike, url);
|
|
3019 g_free(nextline);
|
|
3020 }
|
|
3021
|
|
3022 g_free(text);
|
1
|
3023
|
|
3024
|
|
3025 }
|
|
3026
|
12
|
3027 static char * html_strtok( char * input, char delim )
|
1
|
3028 {
|
12
|
3029 static char * end;
|
|
3030 static char * curr_offset;
|
|
3031 int i;
|
|
3032 int num_quotes=0;
|
|
3033
|
|
3034 if( input != NULL)
|
|
3035 {
|
|
3036 curr_offset = input;
|
|
3037 end = input+strlen(input);
|
|
3038 }
|
|
3039 else
|
|
3040 {
|
|
3041 if( curr_offset + strlen(curr_offset) < end )
|
|
3042 {
|
|
3043 curr_offset += strlen(curr_offset) + 1;
|
|
3044 }
|
|
3045 else
|
|
3046 {
|
|
3047 return NULL;
|
|
3048 }
|
|
3049 }
|
|
3050 for( i=0; curr_offset+i < end &&
|
|
3051 (curr_offset[i] != delim || num_quotes != 0)
|
|
3052 ; i++ )
|
|
3053 {
|
|
3054 if( curr_offset[i] == '\"' )
|
|
3055 {
|
|
3056 num_quotes = (num_quotes+1)%2;
|
|
3057 }
|
|
3058 }
|
|
3059 curr_offset[i] = '\0';
|
|
3060 return curr_offset;
|
|
3061 }
|
|
3062
|
|
3063
|
|
3064 void gtk_html_append_text(GtkHtml * html, char *text, gint options)
|
|
3065 {
|
|
3066 GdkColormap *map;
|
1
|
3067 GdkFont *cfont;
|
12
|
3068 GdkRectangle area;
|
|
3069 char ws[BUF_LONG],
|
|
3070 tag[BUF_LONG],
|
|
3071 *c,
|
|
3072 *url = NULL;
|
|
3073 gint intag = 0,
|
|
3074 wpos = 0,
|
|
3075 tpos = 0,
|
|
3076 colorv,
|
|
3077 bold = 0,
|
|
3078 italic = 0,
|
|
3079 fixed = 0,
|
|
3080 uline = 0,
|
|
3081 strike = 0,
|
|
3082 title = 0;
|
|
3083 gint height;
|
|
3084 struct font_state *current,
|
|
3085 *tmp;
|
|
3086 struct font_state def_state = { 3, 0, 0, "", NULL, NULL, NULL };
|
|
3087
|
|
3088 current = &def_state;
|
|
3089 map = gdk_window_get_colormap(html->html_area);
|
|
3090 cfont = getfont(current->font, bold, italic, fixed, current->size);
|
1
|
3091 c = text;
|
|
3092
|
|
3093
|
12
|
3094 while (*c)
|
|
3095 {
|
|
3096 if (*c == '<')
|
|
3097 {
|
|
3098 if (!intag)
|
|
3099 {
|
|
3100 ws[wpos] = 0;
|
|
3101 if (wpos)
|
|
3102 {
|
|
3103 if (title)
|
|
3104 {
|
|
3105 if (html->title)
|
|
3106 g_free(html->title);
|
|
3107 html->title = g_strdup(ws);
|
|
3108 }
|
|
3109 else
|
|
3110 gtk_html_add_text(html, cfont, current->color,
|
|
3111 current->bgcol, ws, strlen(ws), uline,
|
|
3112 strike, url);
|
|
3113 }
|
|
3114 wpos = 0;
|
|
3115 intag = 1;
|
|
3116 }
|
|
3117 else
|
|
3118 {
|
|
3119 /*
|
|
3120 * Assuming you NEVER have nested tags
|
|
3121 * * (and I mean <tag <tag>> by this, not
|
|
3122 * * <tag><tag2></tag2><tag>..
|
|
3123 */
|
|
3124 tag[tpos] = 0;
|
|
3125 gtk_html_add_text(html, cfont, current->color, current->bgcol,
|
|
3126 "<", 1, 0, 0, NULL);
|
|
3127 gtk_html_add_text(html, cfont, current->color, current->bgcol,
|
|
3128 tag, strlen(tag), 0, 0, NULL);
|
1
|
3129 tpos = 0;
|
12
|
3130
|
|
3131 tag[0] = *c;
|
1
|
3132 }
|
12
|
3133 }
|
|
3134 else if (*c == '>')
|
|
3135 {
|
|
3136 if (intag)
|
|
3137 {
|
|
3138 tag[tpos] = 0;
|
1
|
3139 if (!strcasecmp(tag, "B"))
|
|
3140 bold = 1;
|
|
3141 else if (!strcasecmp(tag, "STRIKE"))
|
|
3142 strike = 1;
|
|
3143 else if (!strcasecmp(tag, "I"))
|
|
3144 italic = 1;
|
|
3145 else if (!strcasecmp(tag, "U"))
|
|
3146 uline = 1;
|
|
3147 else if (!strcasecmp(tag, "PRE"))
|
|
3148 fixed = 1;
|
|
3149 else if (!strcasecmp(tag, "HR"))
|
|
3150 gtk_html_add_seperator(html);
|
|
3151 else if (!strcasecmp(tag, "/B"))
|
|
3152 bold = 0;
|
|
3153 else if (!strcasecmp(tag, "/STRIKE"))
|
|
3154 strike = 0;
|
|
3155 else if (!strcasecmp(tag, "/I"))
|
|
3156 italic = 0;
|
|
3157 else if (!strcasecmp(tag, "/U"))
|
|
3158 uline = 0;
|
|
3159 else if (!strcasecmp(tag, "/PRE"))
|
|
3160 fixed = 0;
|
|
3161 else if (!strcasecmp(tag, "TITLE"))
|
|
3162 title = 1;
|
|
3163 else if (!strcasecmp(tag, "/TITLE"))
|
|
3164 title = 0;
|
12
|
3165 else if (!strncasecmp(tag, "IMG", 3))
|
|
3166 {
|
|
3167
|
|
3168 }
|
|
3169 else if (!strcasecmp(tag, "H3"))
|
|
3170 {
|
1
|
3171 current = push_state(current);
|
|
3172 current->size = 4;
|
12
|
3173 }
|
|
3174 else if (!strcasecmp(tag, "/H3"))
|
|
3175 {
|
|
3176 gtk_html_add_text(html, cfont, current->color,
|
|
3177 current->bgcol, "\n", 1, 0, 0, NULL);
|
|
3178
|
|
3179 if (current->next)
|
|
3180 {
|
1
|
3181 if (current->ownbg)
|
|
3182 g_free(current->bgcol);
|
|
3183 if (current->owncolor)
|
|
3184 g_free(current->color);
|
12
|
3185 tmp = current;
|
|
3186 current = current->next;
|
|
3187 g_free(tmp);
|
1
|
3188 }
|
12
|
3189 }
|
|
3190 else if (!strcasecmp(tag, "TABLE"))
|
|
3191 {
|
|
3192 }
|
|
3193 else if (!strcasecmp(tag, "/TABLE"))
|
|
3194 {
|
|
3195 }
|
|
3196 else if (!strcasecmp(tag, "TR"))
|
|
3197 {
|
|
3198 }
|
|
3199 else if (!strcasecmp(tag, "/TR"))
|
|
3200 {
|
|
3201 }
|
|
3202 else if (!strcasecmp(tag, "/TD"))
|
|
3203 {
|
|
3204 }
|
|
3205 else if (!strcasecmp(tag, "TD"))
|
|
3206 {
|
|
3207 gtk_html_add_text(html, cfont, current->color,
|
|
3208 current->bgcol, " ", 2, 0, 0, NULL);
|
|
3209 }
|
|
3210 else if (!strncasecmp(tag, "A ", 2))
|
|
3211 {
|
1
|
3212 char *d;
|
|
3213 char *temp = d = g_strdup(tag);
|
|
3214 int flag = 0;
|
12
|
3215 strtok(tag, " ");
|
|
3216 while ((d = strtok(NULL, " ")))
|
|
3217 {
|
1
|
3218 if (strlen(d) < 7)
|
|
3219 break;
|
12
|
3220 if (!strncasecmp(d, "HREF=\"", strlen("HREF=\"")))
|
|
3221 {
|
|
3222 d += strlen("HREF=\"");
|
1
|
3223 d[strlen(d) - 1] = 0;
|
|
3224 url = g_malloc(strlen(d) + 1);
|
|
3225 strcpy(url, d);
|
|
3226 flag = 1;
|
12
|
3227 }
|
|
3228 }
|
1
|
3229 g_free(temp);
|
12
|
3230 if (!flag)
|
|
3231 {
|
|
3232 gtk_html_add_text(html, cfont, current->color,
|
|
3233 current->bgcol, "<", 1, 0, 0, NULL);
|
|
3234 gtk_html_add_text(html, cfont, current->color,
|
|
3235 current->bgcol, tag, strlen(tag), 0,
|
|
3236 0, NULL);
|
|
3237 gtk_html_add_text(html, cfont, current->color,
|
|
3238 current->bgcol, ">", 1, 0, 0, NULL);
|
1
|
3239 }
|
12
|
3240 }
|
|
3241 else if (!strcasecmp(tag, "/A"))
|
|
3242 {
|
|
3243 if (url)
|
|
3244 {
|
1
|
3245 g_free(url);
|
|
3246 url = NULL;
|
|
3247 }
|
12
|
3248 }
|
|
3249 else if (!strncasecmp(tag, "FONT", strlen("FONT")))
|
|
3250 {
|
|
3251 char *d;
|
|
3252 /*
|
|
3253 * Push a new state onto the stack, based on the old state
|
|
3254 */
|
|
3255 current = push_state(current);
|
|
3256 html_strtok(tag, ' ');
|
|
3257 while ((d = html_strtok(NULL, ' ')))
|
|
3258 {
|
|
3259 if (!strncasecmp(d, "COLOR=", strlen("COLOR=")))
|
|
3260 {
|
|
3261 d += strlen("COLOR=");
|
|
3262 if (*d == '\"')
|
|
3263 {
|
|
3264 d++;
|
|
3265 }
|
|
3266 if (*d == '#')
|
|
3267 d++;
|
|
3268 if (d[strlen(d) - 1] == '\"')
|
|
3269 d[strlen(d) - 1] = 0;
|
|
3270 if (sscanf(d, "%x", &colorv)
|
|
3271 && !(options & HTML_OPTION_NO_COLOURS))
|
|
3272 {
|
1
|
3273 current->color = get_color(colorv, map);
|
|
3274 current->owncolor = 1;
|
12
|
3275 }
|
|
3276 else
|
|
3277 {
|
1
|
3278 }
|
12
|
3279 }
|
|
3280 if (!strncasecmp(d, "FACE=", strlen("FACE=")))
|
|
3281 {
|
|
3282 d += strlen("FACE=");
|
|
3283 if (*d == '\"')
|
|
3284 {
|
|
3285 d++;
|
|
3286 }
|
1
|
3287 if (d[strlen(d) - 1] == '\"')
|
|
3288 d[strlen(d) - 1] = 0;
|
12
|
3289 strcpy(current->font, d);
|
|
3290 }
|
|
3291 else if (!strncasecmp(d, "BACK=", strlen("BACK=")))
|
|
3292 {
|
|
3293 d += strlen("BACK=");
|
|
3294 if (*d == '\"')
|
|
3295 d++;
|
|
3296 if (*d == '#')
|
|
3297 d++;
|
|
3298 if (d[strlen(d) - 1] == '\"')
|
|
3299 d[strlen(d) - 1] = 0;
|
|
3300 if (sscanf(d, "%x", &colorv)
|
|
3301 && !(options & HTML_OPTION_NO_COLOURS))
|
|
3302 {
|
1
|
3303 current->bgcol = get_color(colorv, map);
|
|
3304 current->ownbg = 1;
|
12
|
3305 }
|
|
3306 else
|
|
3307 {
|
|
3308 }
|
|
3309 }
|
|
3310 else if (!strncasecmp(d, "SIZE=", strlen("SIZE=")))
|
|
3311 {
|
|
3312 d += strlen("SIZE=");
|
|
3313 if (*d == '\"')
|
|
3314 d++;
|
|
3315 if (*d == '+')
|
|
3316 d++;
|
|
3317 if (sscanf(d, "%d", &colorv))
|
|
3318 {
|
|
3319 current->size = colorv;
|
|
3320 }
|
|
3321 else
|
|
3322 {
|
1
|
3323 }
|
12
|
3324 }
|
|
3325 else if (strncasecmp(d, "PTSIZE=", strlen("PTSIZE=")))
|
|
3326 {
|
|
3327 }
|
1
|
3328 }
|
12
|
3329 }
|
|
3330 else
|
|
3331 if (!strncasecmp
|
|
3332 (tag, "BODY BGCOLOR", strlen("BODY BGCOLOR")))
|
|
3333 {
|
|
3334
|
|
3335 /*
|
|
3336 * Ditch trailing \"
|
|
3337 */
|
|
3338 tag[strlen(tag) - 1] = 0;
|
|
3339 if (sscanf(tag + strlen("BODY BGCOLOR=\"#"), "%x", &colorv)
|
|
3340 && !(options & HTML_OPTION_NO_COLOURS))
|
|
3341 {
|
|
3342 current->bgcol = get_color(colorv, map);
|
|
3343 current->ownbg = 1;
|
|
3344 }
|
|
3345 }
|
|
3346 else if (!strncasecmp(tag, "/FONT", strlen("/FONT")))
|
|
3347 {
|
|
3348 /*
|
|
3349 * Pop a font state off the list if possible, freeing
|
|
3350 * any resources it used
|
|
3351 */
|
|
3352 if (current->next)
|
|
3353 {
|
1
|
3354 if (current->ownbg)
|
|
3355 g_free(current->bgcol);
|
|
3356 if (current->owncolor)
|
|
3357 g_free(current->color);
|
12
|
3358 tmp = current;
|
|
3359 current = current->next;
|
|
3360 g_free(tmp);
|
|
3361 }
|
|
3362
|
|
3363 }
|
|
3364 else if (!strcasecmp(tag, "/BODY"))
|
|
3365 {
|
|
3366 if (current->next)
|
|
3367 {
|
|
3368 if (current->ownbg)
|
|
3369 g_free(current->bgcol);
|
|
3370 if (current->owncolor)
|
|
3371 g_free(current->color);
|
|
3372 tmp = current;
|
|
3373 current = current->next;
|
1
|
3374 g_free(tmp);
|
12
|
3375 } /*
|
|
3376 * tags we ignore below
|
|
3377 */
|
|
3378 }
|
|
3379 else if (!strncasecmp(tag, "BR", 2))
|
|
3380 {
|
|
3381 gtk_html_add_text(html, cfont, current->color,
|
|
3382 current->bgcol, "\n", 1, 0, 0, NULL);
|
|
3383 }
|
|
3384 else if (strncasecmp(tag, "HTML", 4)
|
|
3385 && strncasecmp(tag, "/HTML", 5)
|
|
3386 && strncasecmp(tag, "BODY", 4)
|
|
3387 && strncasecmp(tag, "/BODY", 5)
|
|
3388 && strncasecmp(tag, "P", 1)
|
|
3389 && strncasecmp(tag, "/P", 2)
|
|
3390 && strncasecmp(tag, "HEAD", 4)
|
|
3391 && strncasecmp(tag, "/HEAD", 5))
|
|
3392 {
|
|
3393 if (tpos)
|
|
3394 {
|
|
3395 gtk_html_add_text(html, cfont, current->color,
|
|
3396 current->bgcol, "<", 1, 0, 0, NULL);
|
|
3397 gtk_html_add_text(html, cfont, current->color,
|
|
3398 current->bgcol, tag, strlen(tag), 0,
|
|
3399 0, NULL);
|
|
3400 gtk_html_add_text(html, cfont, current->color,
|
|
3401 current->bgcol, ">", 1, 0, 0, NULL);
|
1
|
3402
|
|
3403 }
|
|
3404 }
|
12
|
3405 cfont = getfont(current->font, bold, italic, fixed, current->size);
|
|
3406 tpos = 0;
|
1
|
3407 intag = 0;
|
|
3408 }
|
12
|
3409 else
|
|
3410 {
|
1
|
3411 ws[wpos++] = *c;
|
|
3412 }
|
12
|
3413 }
|
|
3414 else if (!intag && *c == '&')
|
|
3415 {
|
|
3416 if (!strncasecmp(c, "&", 5))
|
|
3417 {
|
|
3418 ws[wpos++] = '&';
|
|
3419 c += 4;
|
|
3420 }
|
|
3421 else if (!strncasecmp(c, "<", 4))
|
|
3422 {
|
|
3423 ws[wpos++] = '<';
|
|
3424 c += 3;
|
|
3425 }
|
|
3426 else if (!strncasecmp(c, ">", 4))
|
|
3427 {
|
|
3428 ws[wpos++] = '>';
|
|
3429 c += 3;
|
|
3430 }
|
|
3431 else if (!strncasecmp(c, " ", 6))
|
|
3432 {
|
|
3433 ws[wpos++] = ' ';
|
|
3434 c += 5;
|
|
3435 }
|
|
3436 else
|
|
3437 {
|
|
3438 ws[wpos++] = *c;
|
|
3439 }
|
|
3440 }
|
|
3441 else
|
|
3442 {
|
|
3443 if (intag)
|
|
3444 {
|
|
3445 tag[tpos++] = *c;
|
|
3446 }
|
|
3447 else
|
|
3448 {
|
|
3449 ws[wpos++] = *c;
|
1
|
3450 }
|
|
3451 }
|
|
3452 c++;
|
|
3453 }
|
12
|
3454 while (current->next)
|
|
3455 {
|
1
|
3456 if (current->ownbg)
|
|
3457 g_free(current->bgcol);
|
|
3458 if (current->owncolor)
|
|
3459 g_free(current->color);
|
|
3460 tmp = current;
|
|
3461 current = current->next;
|
|
3462 g_free(tmp);
|
|
3463 }
|
12
|
3464 ws[wpos] = 0;
|
|
3465 tag[tpos] = 0;
|
|
3466 if (wpos)
|
|
3467 {
|
|
3468 gtk_html_add_text(html, cfont, current->color, current->bgcol, ws,
|
|
3469 strlen(ws), uline, strike, url);
|
1
|
3470 }
|
12
|
3471 if (tpos)
|
|
3472 {
|
|
3473 gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1,
|
|
3474 0, 0, NULL);
|
|
3475 gtk_html_add_text(html, cfont, current->color, current->bgcol, tag,
|
|
3476 strlen(tag), 0, 0, NULL);
|
|
3477 gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1,
|
|
3478 0, 0, NULL);
|
|
3479 }
|
|
3480
|
|
3481
|
|
3482
|
|
3483 gdk_window_get_size(html->html_area, NULL, &height);
|
|
3484 area.height = height;
|
1
|
3485 gtk_adjustment_set_value(html->vadj, html->vadj->upper - area.height);
|
|
3486
|
12
|
3487 return;
|
1
|
3488 }
|
|
3489
|
|
3490
|
12
|
3491 static void adjust_adj(GtkHtml * html, GtkAdjustment * adj)
|
1
|
3492 {
|
12
|
3493 gint height;
|
|
3494
|
|
3495 gdk_window_get_size(html->html_area, NULL, &height);
|
|
3496
|
|
3497 adj->step_increment = MIN(adj->upper, (float) SCROLL_PIXELS);
|
|
3498 adj->page_increment = MIN(adj->upper, height - (float) KEY_SCROLL_PIXELS);
|
|
3499 adj->page_size = MIN(adj->upper, height);
|
|
3500 adj->value = MIN(adj->value, adj->upper - adj->page_size);
|
|
3501 adj->value = MAX(adj->value, 0.0);
|
|
3502
|
|
3503 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
|
1
|
3504 }
|
|
3505
|
|
3506
|
12
|
3507 static void scroll_down(GtkHtml * html, gint diff0)
|
1
|
3508 {
|
12
|
3509 GdkRectangle rect;
|
|
3510 gint width,
|
|
3511 height;
|
|
3512
|
|
3513 html->yoffset += diff0;
|
|
3514
|
|
3515 gdk_window_get_size(html->html_area, &width, &height);
|
|
3516
|
|
3517 if (html->transparent)
|
|
3518 {
|
1
|
3519 rect.x = 0;
|
|
3520 rect.y = 0;
|
|
3521 rect.width = width;
|
|
3522 rect.height = height;
|
12
|
3523 }
|
|
3524 else
|
|
3525 {
|
|
3526
|
1
|
3527
|
|
3528 if (height > diff0 && !html->transparent)
|
12
|
3529 gdk_draw_pixmap(html->html_area,
|
|
3530 html->gc,
|
|
3531 html->html_area,
|
|
3532 0, diff0, 0, 0, width, height - diff0);
|
|
3533
|
|
3534 rect.x = 0;
|
|
3535 rect.y = MAX(0, height - diff0);
|
|
3536 rect.width = width;
|
|
3537 rect.height = MIN(height, diff0);
|
1
|
3538 }
|
12
|
3539
|
|
3540 expose_html(html, &rect, FALSE);
|
|
3541 gtk_html_draw_focus((GtkWidget *) html);
|
1
|
3542
|
|
3543 }
|
|
3544
|
12
|
3545 static void scroll_up(GtkHtml * html, gint diff0)
|
1
|
3546 {
|
12
|
3547 GdkRectangle rect;
|
|
3548 gint width,
|
|
3549 height;
|
|
3550
|
1
|
3551 html->yoffset -= diff0;
|
|
3552
|
|
3553
|
12
|
3554 gdk_window_get_size(html->html_area, &width, &height);
|
|
3555
|
|
3556 if (html->transparent)
|
|
3557 {
|
1
|
3558 rect.x = 0;
|
|
3559 rect.y = 0;
|
|
3560 rect.width = width;
|
|
3561 rect.height = height;
|
12
|
3562 }
|
|
3563 else
|
|
3564 {
|
|
3565
|
1
|
3566 if (height > diff0)
|
12
|
3567 gdk_draw_pixmap(html->html_area,
|
|
3568 html->gc,
|
|
3569 html->html_area,
|
|
3570 0, 0, 0, diff0, width, height - diff0);
|
|
3571
|
|
3572 rect.x = 0;
|
|
3573 rect.y = 0;
|
|
3574 rect.width = width;
|
|
3575 rect.height = MIN(height, diff0);
|
1
|
3576 }
|
|
3577
|
12
|
3578 expose_html(html, &rect, FALSE);
|
|
3579 gtk_html_draw_focus((GtkWidget *) html);
|
1
|
3580
|
|
3581 }
|
|
3582
|
|
3583
|
|
3584
|
12
|
3585 static void gtk_html_adjustment(GtkAdjustment * adjustment, GtkHtml * html)
|
1
|
3586 {
|
12
|
3587 g_return_if_fail(adjustment != NULL);
|
|
3588 g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment));
|
|
3589 g_return_if_fail(html != NULL);
|
|
3590 g_return_if_fail(GTK_IS_HTML(html));
|
|
3591
|
|
3592 /*
|
|
3593 * Just ignore it if we haven't been size-allocated and realized yet
|
|
3594 */
|
|
3595 if (html->html_area == NULL)
|
|
3596 return;
|
|
3597
|
|
3598 if (adjustment == html->hadj)
|
|
3599 {
|
|
3600 g_warning("horizontal scrolling not implemented");
|
|
3601 }
|
|
3602 else
|
|
3603 {
|
|
3604 gint diff = ((gint) adjustment->value) - html->last_ver_value;
|
|
3605
|
|
3606 if (diff != 0)
|
|
3607 {
|
|
3608 /*
|
|
3609 * undraw_cursor (text, FALSE);
|
|
3610 */
|
|
3611
|
|
3612 if (diff > 0)
|
|
3613 {
|
|
3614 scroll_down(html, diff);
|
|
3615 }
|
|
3616 else
|
|
3617 { /*
|
|
3618 * if (diff < 0)
|
|
3619 */
|
|
3620 scroll_up(html, -diff);
|
|
3621 }
|
|
3622 /*
|
|
3623 * draw_cursor (text, FALSE);
|
|
3624 */
|
|
3625
|
|
3626 html->last_ver_value = adjustment->value;
|
|
3627 }
|
|
3628 }
|
1
|
3629 }
|
12
|
3630
|
|
3631 static gint gtk_html_visibility_notify(GtkWidget * widget,
|
|
3632 GdkEventVisibility * event)
|
1
|
3633 {
|
|
3634 GtkHtml *html;
|
|
3635 GdkRectangle rect;
|
12
|
3636 gint width,
|
|
3637 height;
|
|
3638
|
|
3639 g_return_val_if_fail(widget != NULL, FALSE);
|
|
3640 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
|
|
3641
|
|
3642 html = GTK_HTML(widget);
|
|
3643
|
|
3644 if (GTK_WIDGET_REALIZED(widget) && html->transparent)
|
|
3645 {
|
|
3646 gdk_window_get_size(html->html_area, &width, &height);
|
|
3647 rect.x = 0;
|
|
3648 rect.y = 0;
|
|
3649 rect.width = width;
|
|
3650 rect.height = height;
|
|
3651 expose_html(html, &rect, FALSE);
|
|
3652 gtk_html_draw_focus((GtkWidget *) html);
|
|
3653 }
|
|
3654 else
|
|
3655 {
|
1
|
3656 }
|
|
3657
|
|
3658
|
12
|
3659 return FALSE;
|
1
|
3660 }
|
|
3661
|
|
3662
|
|
3663
|
12
|
3664 static void gtk_html_disconnect(GtkAdjustment * adjustment, GtkHtml * html)
|
1
|
3665 {
|
12
|
3666 g_return_if_fail(adjustment != NULL);
|
|
3667 g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment));
|
|
3668 g_return_if_fail(html != NULL);
|
|
3669 g_return_if_fail(GTK_IS_HTML(html));
|
|
3670
|
|
3671 if (adjustment == html->hadj)
|
|
3672 gtk_html_set_adjustments(html, NULL, html->vadj);
|
|
3673 if (adjustment == html->vadj)
|
|
3674 gtk_html_set_adjustments(html, html->hadj, NULL);
|
1
|
3675 }
|
|
3676
|
12
|
3677 static void move_cursor_ver(GtkHtml * html, int count)
|
1
|
3678 {
|
|
3679 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
12
|
3680 GtkHtmlBit *hb = NULL,
|
|
3681 *hb2 = NULL;
|
1
|
3682 gint y;
|
12
|
3683 gint len,
|
|
3684 len2 = 0;
|
|
3685
|
1
|
3686 undraw_cursor(html);
|
|
3687
|
|
3688 if (!html->html_bits)
|
|
3689 return;
|
12
|
3690
|
1
|
3691 if (!html->cursor_hb)
|
12
|
3692 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
|
1
|
3693
|
|
3694 hb = html->cursor_hb;
|
|
3695
|
|
3696 len = html->cursor_pos;
|
|
3697 hbits = hbits->prev;
|
12
|
3698 while (hbits)
|
|
3699 {
|
|
3700 hb2 = (GtkHtmlBit *) hbits->data;
|
1
|
3701
|
|
3702 if (hb2->y != hb->y)
|
|
3703 break;
|
|
3704
|
12
|
3705 len += strlen(hb2->text);
|
|
3706
|
1
|
3707 hbits = hbits->prev;
|
|
3708 }
|
|
3709
|
12
|
3710 hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3711
|
|
3712 if (count < 0)
|
|
3713 {
|
|
3714 while (hbits)
|
|
3715 {
|
|
3716 hb2 = (GtkHtmlBit *) hbits->data;
|
1
|
3717
|
|
3718 if (hb2->y != hb->y)
|
|
3719 break;
|
12
|
3720
|
1
|
3721 hbits = hbits->prev;
|
|
3722 }
|
12
|
3723 if (!hbits)
|
|
3724 {
|
1
|
3725 draw_cursor(html);
|
|
3726 return;
|
|
3727 }
|
|
3728 y = hb2->y;
|
|
3729 hb = hb2;
|
12
|
3730 while (hbits)
|
|
3731 {
|
|
3732 hb2 = (GtkHtmlBit *) hbits->data;
|
1
|
3733
|
|
3734 if (hb2->y != y)
|
|
3735 break;
|
|
3736
|
|
3737 hb = hb2;
|
12
|
3738
|
1
|
3739 hbits = hbits->prev;
|
|
3740 }
|
|
3741 hbits = g_list_find(html->html_bits, hb);
|
12
|
3742 while (hbits)
|
|
3743 {
|
|
3744 hb2 = (GtkHtmlBit *) hbits->data;
|
|
3745
|
|
3746 if (hb->y != hb2->y)
|
|
3747 {
|
1
|
3748 html->cursor_hb = hb;
|
|
3749 html->cursor_pos = strlen(hb->text);
|
12
|
3750 break;
|
1
|
3751 }
|
|
3752
|
|
3753
|
12
|
3754 if (len < len2 + strlen(hb2->text))
|
|
3755 {
|
1
|
3756 html->cursor_hb = hb2;
|
|
3757 html->cursor_pos = len - len2;
|
|
3758 break;
|
|
3759 }
|
|
3760
|
|
3761 len2 += strlen(hb2->text);
|
|
3762
|
|
3763 hb = hb2;
|
|
3764
|
12
|
3765 hbits = hbits->next;
|
1
|
3766 }
|
12
|
3767 }
|
|
3768 else
|
|
3769 {
|
|
3770 while (hbits)
|
|
3771 {
|
|
3772 hb2 = (GtkHtmlBit *) hbits->data;
|
1
|
3773
|
|
3774 if (hb2->y != hb->y)
|
|
3775 break;
|
12
|
3776
|
1
|
3777 hbits = hbits->next;
|
|
3778 }
|
12
|
3779 if (!hbits)
|
|
3780 {
|
1
|
3781 draw_cursor(html);
|
|
3782 return;
|
|
3783 }
|
|
3784 hb = hb2;
|
12
|
3785 while (hbits)
|
|
3786 {
|
|
3787 hb2 = (GtkHtmlBit *) hbits->data;
|
|
3788
|
|
3789 if (hb->y != hb2->y)
|
|
3790 {
|
1
|
3791 html->cursor_hb = hb;
|
|
3792 html->cursor_pos = strlen(hb->text);
|
12
|
3793 break;
|
1
|
3794 }
|
|
3795
|
|
3796
|
12
|
3797 if (len < len2 + strlen(hb2->text))
|
|
3798 {
|
1
|
3799 html->cursor_hb = hb2;
|
|
3800 html->cursor_pos = len - len2;
|
|
3801 break;
|
|
3802 }
|
|
3803
|
|
3804 len2 += strlen(hb2->text);
|
|
3805
|
|
3806 hb = hb2;
|
|
3807
|
12
|
3808 hbits = hbits->next;
|
1
|
3809 }
|
|
3810 }
|
|
3811
|
|
3812 draw_cursor(html);
|
|
3813
|
|
3814 }
|
|
3815
|
12
|
3816 static void move_cursor_hor(GtkHtml * html, int count)
|
1
|
3817 {
|
|
3818 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
12
|
3819 GtkHtmlBit *hb,
|
|
3820 *hb2;
|
1
|
3821
|
|
3822 undraw_cursor(html);
|
|
3823
|
|
3824 if (!html->html_bits)
|
|
3825 return;
|
12
|
3826
|
1
|
3827 if (!html->cursor_hb)
|
12
|
3828 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
|
|
3829
|
|
3830 html->cursor_pos += count;
|
|
3831
|
|
3832 if (html->cursor_pos < 0)
|
|
3833 {
|
|
3834 if (hbits->prev)
|
|
3835 {
|
1
|
3836 gint diff;
|
|
3837 hb = html->cursor_hb;
|
12
|
3838 hb2 = (GtkHtmlBit *) hbits->prev->data;
|
1
|
3839 diff = html->cursor_pos + strlen(hb2->text) + 1;
|
|
3840 if (hb->y == hb2->y)
|
|
3841 --diff;
|
12
|
3842
|
1
|
3843 html->cursor_pos = diff;
|
12
|
3844
|
|
3845 html->cursor_hb = (GtkHtmlBit *) hbits->prev->data;
|
|
3846 }
|
|
3847 else
|
|
3848 {
|
1
|
3849 html->cursor_pos = 0;
|
|
3850 }
|
12
|
3851 }
|
|
3852 else if (html->cursor_pos > strlen(html->cursor_hb->text))
|
|
3853 {
|
|
3854 if (hbits->next)
|
|
3855 {
|
1
|
3856 gint diff;
|
|
3857 hb = html->cursor_hb;
|
12
|
3858 hb2 = (GtkHtmlBit *) hbits->next->data;
|
1
|
3859
|
|
3860 diff = html->cursor_pos - strlen(html->cursor_hb->text) - 1;
|
|
3861 if (hb->y == hb2->y)
|
12
|
3862 ++diff;
|
1
|
3863 html->cursor_pos = diff;
|
12
|
3864 html->cursor_hb = (GtkHtmlBit *) hbits->next->data;
|
|
3865 }
|
|
3866 else
|
|
3867 {
|
1
|
3868 html->cursor_pos = strlen(html->cursor_hb->text);
|
|
3869 }
|
|
3870
|
|
3871 }
|
|
3872
|
|
3873 draw_cursor(html);
|
|
3874 }
|
|
3875
|
12
|
3876 static void move_beginning_of_line(GtkHtml * html)
|
1
|
3877 {
|
|
3878 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3879 GtkHtmlBit *hb = NULL;
|
12
|
3880 gint y;
|
|
3881
|
1
|
3882 undraw_cursor(html);
|
|
3883
|
|
3884 if (!html->html_bits)
|
|
3885 return;
|
|
3886
|
|
3887 if (!html->cursor_hb)
|
12
|
3888 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
|
1
|
3889
|
|
3890 y = html->cursor_hb->y;
|
12
|
3891
|
|
3892 while (hbits)
|
|
3893 {
|
|
3894 hb = (GtkHtmlBit *) hbits->data;
|
|
3895
|
|
3896 if (y != hb->y)
|
|
3897 {
|
|
3898 hb = (GtkHtmlBit *) hbits->next->data;
|
1
|
3899 break;
|
|
3900 }
|
12
|
3901
|
1
|
3902 hbits = hbits->prev;
|
|
3903 }
|
|
3904 if (!hbits)
|
12
|
3905 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
|
1
|
3906 else
|
|
3907 html->cursor_hb = hb;
|
|
3908
|
|
3909 html->cursor_pos = 0;
|
|
3910
|
|
3911
|
|
3912 draw_cursor(html);
|
|
3913
|
|
3914
|
|
3915 }
|
|
3916
|
12
|
3917 static void move_end_of_line(GtkHtml * html)
|
1
|
3918 {
|
|
3919 GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
|
|
3920 GtkHtmlBit *hb = NULL;
|
12
|
3921 gint y;
|
|
3922
|
1
|
3923 undraw_cursor(html);
|
|
3924
|
|
3925 if (!html->html_bits)
|
|
3926 return;
|
|
3927
|
|
3928 if (!html->cursor_hb)
|
12
|
3929 html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
|
1
|
3930
|
|
3931 y = html->cursor_hb->y;
|
12
|
3932
|
|
3933 while (hbits)
|
|
3934 {
|
|
3935 hb = (GtkHtmlBit *) hbits->data;
|
|
3936
|
|
3937 if (y != hb->y)
|
|
3938 {
|
|
3939 hb = (GtkHtmlBit *) hbits->prev->data;
|
1
|
3940 break;
|
|
3941 }
|
12
|
3942
|
1
|
3943 hbits = hbits->next;
|
|
3944 }
|
|
3945 if (!hbits)
|
12
|
3946 html->cursor_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data;
|
1
|
3947 else
|
|
3948 html->cursor_hb = hb;
|
|
3949
|
|
3950 html->cursor_pos = strlen(html->cursor_hb->text);
|
|
3951
|
|
3952
|
|
3953 draw_cursor(html);
|
|
3954
|
|
3955
|
|
3956 }
|
|
3957
|
|
3958
|
|
3959
|
12
|
3960 static gint gtk_html_key_press(GtkWidget * widget, GdkEventKey * event)
|
1
|
3961 {
|
|
3962 GtkHtml *html;
|
|
3963 gchar key;
|
|
3964 gint return_val;
|
12
|
3965
|
|
3966 g_return_val_if_fail(widget != NULL, FALSE);
|
|
3967 g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
|
|
3968 g_return_val_if_fail(event != NULL, FALSE);
|
|
3969
|
1
|
3970 return_val = FALSE;
|
12
|
3971
|
|
3972 html = GTK_HTML(widget);
|
|
3973
|
1
|
3974 key = event->keyval;
|
|
3975 return_val = TRUE;
|
|
3976
|
|
3977
|
12
|
3978 if (html->editable == FALSE)
|
|
3979 {
|
|
3980 /*
|
|
3981 * switch (event->keyval) {
|
|
3982 * case GDK_Home:
|
|
3983 * if (event->state & GDK_CONTROL_MASK)
|
|
3984 * scroll_int (text, -text->vadj->value);
|
|
3985 * else
|
|
3986 * return_val = FALSE;
|
|
3987 * break;
|
|
3988 * case GDK_End:
|
|
3989 * if (event->state & GDK_CONTROL_MASK)
|
|
3990 * scroll_int (text, +text->vadj->upper);
|
|
3991 * else
|
|
3992 * return_val = FALSE;
|
|
3993 * break;
|
|
3994 * case GDK_Page_Up: scroll_int (text, -text->vadj->page_increment); break;
|
|
3995 * case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break;
|
|
3996 * case GDK_Up: scroll_int (text, -KEY_SCROLL_PIXELS); break;
|
|
3997 * case GDK_Down: scroll_int (text, +KEY_SCROLL_PIXELS); break;
|
|
3998 * case GDK_Return:
|
|
3999 * if (event->state & GDK_CONTROL_MASK)
|
|
4000 * gtk_signal_emit_by_name (GTK_OBJECT (text), "activate");
|
|
4001 * else
|
|
4002 * return_val = FALSE;
|
|
4003 * break;
|
|
4004 * default:
|
|
4005 * return_val = FALSE;
|
|
4006 * break;
|
|
4007 * }
|
|
4008 */
|
|
4009 }
|
|
4010 else
|
|
4011 {
|
|
4012
|
|
4013 switch (event->keyval)
|
|
4014 {
|
1
|
4015 case GDK_Home:
|
12
|
4016 move_beginning_of_line(html);
|
1
|
4017 break;
|
|
4018 case GDK_End:
|
12
|
4019 move_end_of_line(html);
|
1
|
4020 break;
|
|
4021 /*
|
12
|
4022 * case GDK_Page_Up:
|
|
4023 * move_cursor_page_ver (html, -1);
|
|
4024 * break;
|
|
4025 * case GDK_Page_Down:
|
|
4026 * move_cursor_page_ver (html, +1);
|
|
4027 * break;
|
|
4028 */
|
|
4029 /*
|
|
4030 * CUA has Ctrl-Up/Ctrl-Down as paragraph up down
|
|
4031 */
|
1
|
4032 case GDK_Up:
|
12
|
4033 move_cursor_ver(html, -1);
|
1
|
4034 break;
|
|
4035 case GDK_Down:
|
12
|
4036 move_cursor_ver(html, +1);
|
1
|
4037 break;
|
|
4038 case GDK_Left:
|
12
|
4039 move_cursor_hor(html, -1);
|
1
|
4040 break;
|
|
4041 case GDK_Right:
|
12
|
4042 move_cursor_hor(html, +1);
|
1
|
4043 break;
|
|
4044 #if 0
|
|
4045 case GDK_BackSpace:
|
|
4046 if (event->state & GDK_CONTROL_MASK)
|
12
|
4047 gtk_text_delete_backward_word(text);
|
1
|
4048 else
|
12
|
4049 gtk_text_delete_backward_character(text);
|
1
|
4050 break;
|
|
4051 case GDK_Clear:
|
12
|
4052 gtk_text_delete_line(text);
|
1
|
4053 break;
|
|
4054 case GDK_Insert:
|
|
4055 if (event->state & GDK_SHIFT_MASK)
|
|
4056 {
|
|
4057 extend_selection = FALSE;
|
12
|
4058 gtk_editable_paste_clipboard(editable);
|
1
|
4059 }
|
|
4060 else if (event->state & GDK_CONTROL_MASK)
|
|
4061 {
|
12
|
4062 gtk_editable_copy_clipboard(editable);
|
1
|
4063 }
|
|
4064 else
|
|
4065 {
|
12
|
4066 /*
|
|
4067 * gtk_toggle_insert(text) -- IMPLEMENT
|
|
4068 */
|
1
|
4069 }
|
|
4070 break;
|
|
4071 case GDK_Delete:
|
|
4072 if (event->state & GDK_CONTROL_MASK)
|
12
|
4073 gtk_text_delete_forward_word(text);
|
1
|
4074 else if (event->state & GDK_SHIFT_MASK)
|
|
4075 {
|
|
4076 extend_selection = FALSE;
|
12
|
4077 gtk_editable_cut_clipboard(editable);
|
1
|
4078 }
|
|
4079 else
|
12
|
4080 gtk_text_delete_forward_character(text);
|
1
|
4081 break;
|
|
4082 case GDK_Tab:
|
|
4083 position = text->point.index;
|
12
|
4084 gtk_editable_insert_text(editable, "\t", 1, &position);
|
1
|
4085 break;
|
|
4086 case GDK_Return:
|
|
4087 if (event->state & GDK_CONTROL_MASK)
|
12
|
4088 gtk_signal_emit_by_name(GTK_OBJECT(text), "activate");
|
1
|
4089 else
|
|
4090 {
|
|
4091 position = text->point.index;
|
12
|
4092 gtk_editable_insert_text(editable, "\n", 1, &position);
|
1
|
4093 }
|
|
4094 break;
|
|
4095 case GDK_Escape:
|
12
|
4096 /*
|
|
4097 * Don't insert literally
|
|
4098 */
|
1
|
4099 return_val = FALSE;
|
|
4100 break;
|
|
4101 #endif
|
|
4102 default:
|
|
4103 return_val = FALSE;
|
|
4104
|
|
4105 #if 0
|
12
|
4106 if (event->state & GDK_CONTROL_MASK)
|
|
4107 {
|
1
|
4108 if ((key >= 'A') && (key <= 'Z'))
|
|
4109 key -= 'A' - 'a';
|
|
4110
|
12
|
4111 if ((key >= 'a') && (key <= 'z')
|
|
4112 && control_keys[(int) (key - 'a')])
|
1
|
4113 {
|
12
|
4114 (*control_keys[(int) (key - 'a')]) (editable, event->time);
|
1
|
4115 return_val = TRUE;
|
|
4116 }
|
|
4117
|
|
4118 break;
|
|
4119 }
|
|
4120 else if (event->state & GDK_MOD1_MASK)
|
|
4121 {
|
|
4122 if ((key >= 'A') && (key <= 'Z'))
|
|
4123 key -= 'A' - 'a';
|
|
4124
|
|
4125 if ((key >= 'a') && (key <= 'z') && alt_keys[(int) (key - 'a')])
|
|
4126 {
|
12
|
4127 (*alt_keys[(int) (key - 'a')]) (editable, event->time);
|
1
|
4128 return_val = TRUE;
|
|
4129 }
|
|
4130 break;
|
|
4131 }
|
|
4132 #endif
|
|
4133 /*
|
12
|
4134 * if (event->length > 0) {
|
|
4135 * html->cursor_pos++;
|
|
4136 * gtk_editable_insert_text (editable, event->string, event->length, &position);
|
|
4137 *
|
|
4138 * return_val = TRUE;
|
|
4139 * }
|
|
4140 * else
|
|
4141 * return_val = FALSE;
|
|
4142 */
|
1
|
4143 }
|
|
4144
|
|
4145 }
|
|
4146
|
|
4147 return return_val;
|
|
4148 }
|
12
|
4149
|
|
4150 void gtk_html_freeze(GtkHtml * html)
|
1
|
4151 {
|
12
|
4152 g_return_if_fail(html != NULL);
|
|
4153 g_return_if_fail(GTK_IS_HTML(html));
|
1
|
4154
|
|
4155 html->frozen++;
|
|
4156 }
|
|
4157
|
12
|
4158 void gtk_html_thaw(GtkHtml * html)
|
1
|
4159 {
|
|
4160 GdkRectangle area;
|
12
|
4161
|
|
4162 g_return_if_fail(html != NULL);
|
|
4163 g_return_if_fail(GTK_IS_HTML(html));
|
1
|
4164
|
|
4165 html->frozen--;
|
|
4166
|
|
4167 if (html->frozen < 0)
|
12
|
4168 html->frozen = 0;
|
|
4169
|
|
4170 if (html->frozen == 0)
|
|
4171 {
|
|
4172 if (html->html_area)
|
|
4173 {
|
|
4174 gint width,
|
|
4175 height;
|
1
|
4176 area.x = 0;
|
|
4177 area.y = 0;
|
|
4178
|
|
4179 gdk_window_get_size(html->html_area, &width, &height);
|
|
4180
|
12
|
4181 area.width = width;
|
|
4182 area.height = height;
|
|
4183
|
1
|
4184 expose_html(html, &area, TRUE);
|
|
4185 }
|
|
4186 }
|
|
4187 }
|