1 #ifndef production
2 static char rcsId[]="$Header$";
3 #endif
4 /*****
5 * private.c : Private XmHTML functions that don't depend on X Intrinsics
6 * or Motif.
7 *
8 * This file Version $Revision$
9 *
10 * Creation date: Tue Apr 14 16:13:32 GMT+0100 1998
11 * Last modification: $Date$
12 * By: $Author$
13 * Current State: $State$
14 *
15 * Author: newt
16 *
17 * Copyright (C) 1994-1998 by Ripley Software Development
18 * All Rights Reserved
19 *
20 * This file is part of the XmHTML Widget Library
21 *
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Library General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
26 *
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Library General Public License for more details.
31 *
32 * You should have received a copy of the GNU Library General Public
33 * License along with this library; if not, write to the Free
34 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *
36 *****/
37 /*****
38 * ChangeLog
39 * $Log$
40 * Revision 1.3 2012/03/01 17:56:31 ziad
41 * Cput
42 *
43 * Revision 1.2 2011/11/10 14:37:55 ziad
44 * Cput
45 *
46 * Revision 1.1 2011/06/30 16:10:38 rwcox
47 * Cadd
48 *
49 * Revision 1.1 1998/04/27 06:54:13 newt
50 * Initial Revision
51 *
52 *****/
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <ctype.h>
61
62 /* Our private header files */
63 #include "toolkit.h"
64 #include XmHTMLPrivateHeader
65
66 /*** External Function Prototype Declarations ***/
67 extern void _XmHTMLScrollForm(XmHTMLWidget html);
68 extern void _XmHTMLAutoSizeWidget(XmHTMLWidget html);
69
70 /*** Public Variable Declarations ***/
71
72 /*** Private Datatype Declarations ****/
73
74 /*** Private Function Prototype Declarations ****/
75 void PaintBackground(XmHTMLWidget html, int x, int y, int width, int height);
76
77 /*** Private Variable Declarations ***/
78
79 /*****
80 * Name: _XmHTMLRefresh
81 * Return Type: void
82 * Description: main screen refresher: given an exposure rectangle, this
83 * routine determines the proper paint engine start and end
84 * points and calls the painter.
85 * In:
86 * html: XmHTMLWidget id
87 * x,y: upper-left corner of exposure region
88 * width: width of exposure region
89 * height: height of exposure region
90 * Returns:
91 * nothing.
92 *****/
93 void
_XmHTMLRefresh(XmHTMLWidget html,int x,int y,int width,int height)94 _XmHTMLRefresh(XmHTMLWidget html, int x, int y, int width, int height)
95 {
96 int x1, x2, y1, y2, dy;
97 XmHTMLObjectTable *start, *end;
98
99 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh Start\n"));
100
101 x1 = x;
102 x2 = x1 + width;
103
104 /*
105 * Update background with the given region. Must check if body image
106 * hasn't been delayed or is being loaded progressively or we will get
107 * some funny effects...
108 */
109 if(HTML_ATTR(body_image) && !ImageDelayedCreation(HTML_ATTR(body_image)) &&
110 BodyImageLoaded(HTML_ATTR(body_image)->html_image))
111 PaintBackground(html, x, y, width, height);
112
113 /*
114 * We add the fontheight to the height of the exposure region. This will
115 * ensure that the line right under the exposure region is also redrawn
116 * properly. Same for topmost position, but subtraction instead of addition.
117 */
118 dy = HTML_ATTR(default_font)->lineheight;
119 y1 = (y - dy > 0 ? y - dy : y);
120 y2 = y1 + height + 1.5*dy;
121
122 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, initial y1: %i, y2: %i\n",
123 y1, y2));
124 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, initial x1: %i, x2: %i\n",
125 x1, x2));
126
127 /* add vertical scroll and core offsets */
128 y1 += HTML_ATTR(scroll_y) - CORE_ATTR(y);
129 y2 += HTML_ATTR(scroll_y) + CORE_ATTR(y);
130
131 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, using y1: %i, y2: %i "
132 "(scroll_y = %i, core.y = %i)\n", y1, y2, HTML_ATTR(scroll_y),
133 CORE_ATTR(y)));
134
135 /*
136 * If the offset of the top of the exposed region is higher than
137 * the max height of the text to display, the exposure region
138 * is empty, so we just return here and leave everything untouched.
139 */
140 if(y1 > HTML_ATTR(formatted_height))
141 {
142 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh End, y1 > maximum document "
143 " height\n"));
144 HTML_ATTR(top_line) = HTML_ATTR(nlines);
145 return;
146 }
147
148 /*
149 * Get paint stream start & end for the obtained exposure region
150 * We have to take the height of the object into account as well.
151 * We try to be a little bit smart here.
152 * paint_start == NULL is a valid stream command, so check it.
153 */
154 start = (HTML_ATTR(paint_start) ?
155 HTML_ATTR(paint_start) : HTML_ATTR(formatted));
156
157 /* sanity */
158 if(start == NULL)
159 return;
160
161 /* below current paint engine start, scrolling down */
162 if(y1 > start->y)
163 {
164 /* already in region, get first object in it */
165 if(y1 < (start->y + start->height))
166 {
167 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, walking bottom-up, "
168 "y_start = %i\n", start->y));
169 while(start && y1 > start->y && y1 < (start->y + start->height))
170 start = start->prev;
171 }
172 /* below region, walk forward until we hit first object */
173 else
174 {
175 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, walking bottom-down, "
176 "y_start = %i\n", start->y));
177 while(start)
178 {
179 if(y1 > start->y && y1 < (start->y + start->height))
180 break;
181 start = start->next;
182 }
183 }
184 }
185 /* above current paint engine start, scrolling up */
186 else
187 {
188 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, walking top-up, "
189 "y_start = %i\n", start->y));
190
191 while(start && y1 <= start->y)
192 start = start->prev;
193
194 start = (start ? start : HTML_ATTR(formatted));
195 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, got y = %i (y1 = %i)\n",
196 start->y, y1));
197
198 /* get first object with same y position */
199 while(start && start->prev && start->y == start->prev->y)
200 start = start->prev;
201 }
202
203 /* sanity check */
204 if(start == NULL)
205 start = HTML_ATTR(formatted);
206 end = start;
207
208 /* get first point at bottom of exposed region */
209 while(end && y2 > end->y)
210 end = end->next;
211 /* now walk to the last point still inside the region */
212 while(end && y2 > end->y && y2 < (end->y + end->height))
213 end = end->next;
214
215 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, initial start point, "
216 "start->x = %i, start->y = %i\n", start->x, start->y));
217
218 /*****
219 * If start is part of a table, painting starts at the first cell in a
220 * row
221 *****/
222 if(start->table)
223 {
224 XmHTMLTable *table;
225 TableRow *row = NULL;
226 TableCell *cell = NULL;
227 int i, j;
228 XmHTMLObjectTable *ts=NULL;
229
230 table = start->table;
231 if(table->childs)
232 table = &(table->childs[0]);
233
234 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, start located in table, "
235 "looking, for current row.\n"));
236
237 /* locate row where element is located */
238 for(i = 0; i < table->nrows; i++)
239 {
240 row = &(table->rows[i]);
241 if(row->owner == start)
242 {
243 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, start found as "
244 "row %i.\n\t(y = %i, height = %i)\n", i, start->y,
245 start->height));
246 break;
247 }
248 for(j = 0; j < row->ncells; j++)
249 {
250 cell = &(row->cells[j]);
251 if(cell->owner == start)
252 {
253 ts = start;
254 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, start found "
255 "as cell %i in row %i\n\t(y = %i, height = %i)\n",
256 j, i, ts->y, ts->height));
257 break;
258 }
259 for(ts = cell->owner; ts && ts != cell->end && ts != start;
260 ts = ts->next);
261 if(ts == start)
262 {
263 ts = start;
264 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, start found "
265 "in cell %i, row %i\n\t(y = %i, height = %i)\n",
266 j, i, ts->y, ts->height));
267 break;
268 }
269 }
270 if(ts == start)
271 {
272 start = row->owner;
273 break;
274 }
275 }
276 /* fallback */
277 if(i == table->nrows)
278 {
279 start = start->table->start;
280 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, start nowhere to "
281 "be found, setting to first element in table.\n\t(y = %i, "
282 "height = %i)\n", start->y, start->height));
283 }
284 }
285
286 /* set proper paint engine start & end */
287 HTML_ATTR(paint_start) = start;
288 HTML_ATTR(paint_end) = end;
289
290 /* Set horizontal painting positions */
291 HTML_ATTR(paint_x) = x1 + HTML_ATTR(scroll_x) - CORE_ATTR(x);
292 HTML_ATTR(paint_width) = x2 + HTML_ATTR(scroll_x) + CORE_ATTR(x);
293
294 /* Set vertical painting positions */
295 HTML_ATTR(paint_y) = y1;
296 HTML_ATTR(paint_height) = y2;
297
298 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, x1 = %i, x2 = %i\n", x1, x2));
299 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, y1 = %i, y2 = %i\n", y1, y2));
300 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, paint_start->x = %i, "
301 "paint_start->y = %i\n", start->x, start->y));
302 #ifdef DEBUG
303 if(end)
304 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, paint_end->x = %i, "
305 "paint_end->y = %i\n", end->x, end->y));
306 else
307 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, paint_end is NULL!\n"));
308 #endif
309
310 if(HTML_ATTR(gc) == NULL)
311 return;
312
313 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLRefresh, calling _XmHTMLPaint\n"));
314 _XmHTMLPaint(html, HTML_ATTR(paint_start), HTML_ATTR(paint_end));
315
316 #if 0
317 /* doesn't work yet */
318 if(HTML_ATTR(is_frame && HTML_ATTR(frame_border)
319 _XmHTMLDrawFrameBorder(html);
320 #endif
321
322 /* display scrollbars */
323 _XmHTMLSetScrollBars(html);
324 }
325
326 /*****
327 * Name: PaintBackground
328 * Return Type: void
329 * Description: update background with the given region
330 * In:
331 * html: XmHTMLWidget for which to do background painting.
332 * x,y: origin of region to update
333 * width,height: dimensions of region to update.
334 * Returns:
335 * nothing.
336 * Note:
337 * A simple and beautiful routine that does it's job perfectly!
338 *****/
339 void
PaintBackground(XmHTMLWidget html,int x,int y,int width,int height)340 PaintBackground(XmHTMLWidget html, int x, int y, int width, int height)
341 {
342 int tile_width, tile_height, x_dist, y_dist, ntiles_x, ntiles_y;
343 int x_offset, y_offset, tsx, tsy;
344 ToolkitAbstraction *tka = HTML_ATTR(tka);
345
346 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground start, x = %i, y = %i, "
347 "width = %i, height = %i\n", x, y, width, height));
348
349 /* fix 02/06/98-01, eb */
350 /* not realized yet */
351 if(!tka || !tka->win)
352 return;
353
354 /*****
355 * We need to figure out a correct starting point for the first
356 * tile to be drawn (ts_[x,y]_origin in the GC).
357 * We know the region to update. First we need to get the number of tiles
358 * drawn so far. Since we want the *total* number of tiles drawn, we must
359 * add the scroll offsets to the region origin.
360 *****/
361 tile_width = HTML_ATTR(body_image)->width;
362 tile_height = HTML_ATTR(body_image)->height;
363
364 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, tile width = %i, "
365 "tile height = %i\n", tile_width, tile_height));
366
367 x_dist = HTML_ATTR(scroll_x) + x;
368 y_dist = HTML_ATTR(scroll_y) + y;
369
370 ntiles_x = (int)(x_dist/tile_width);
371 ntiles_y = (int)(y_dist/tile_height);
372
373 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, no of full drawn "
374 "horizontal tiles: %i (x_dist = %i)\n", ntiles_x, x_dist));
375 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, no of full drawn "
376 "vertical tiles : %i (y_dist = %i)\n", ntiles_y, y_dist));
377 /*
378 * Now we know how many full tiles have been drawn, we can calculate
379 * the horizontal and vertical shifts required to start tiling on a
380 * tile boundary.
381 */
382 x_offset = x_dist - ntiles_x * tile_width;
383 y_offset = y_dist - ntiles_y * tile_height;
384
385 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, computed horizontal "
386 "offset: %i\n", x_offset));
387 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, computed vertical "
388 "offset : %i\n", y_offset));
389 /*
390 * Now we can compute the x and y tile origins. Note that these can
391 * be negative.
392 */
393 tsx = x - x_offset;
394 tsy = y - y_offset;
395
396 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, computed horizontal "
397 "tile origin: %i (x = %i)\n", tsx, x));
398 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground, computed vertical "
399 "tile origin : %i (y = %i)\n", tsy, y));
400
401 tka->SetFillStyle(tka->dpy, HTML_ATTR(bg_gc),
402 tka->fill_style[GC_FILL_TILED]);
403 tka->SetTile(tka->dpy, HTML_ATTR(bg_gc), HTML_ATTR(body_image)->pixmap);
404 tka->SetTSOrigin(tka->dpy, HTML_ATTR(bg_gc), tsx, tsy);
405
406 /* a plain fillrect will redraw the background portion */
407 tka->FillRectangle(tka->dpy, tka->win, HTML_ATTR(bg_gc),
408 x, y, width, height);
409
410 _XmHTMLDebug(1, ("XmHTML.c: PaintBackground end\n"));
411 }
412
413
414 /*****
415 * Name: _XmHTMLGetAnchor
416 * Return Type: XmHTMLWord*
417 * Description: determines if the given x and y positions are within the
418 * bounding rectangle of an anchor.
419 * In:
420 * w: HTML widget to check
421 * x,y: position to validate
422 * img: image if anchor is part of an anchored image map.
423 * Returns:
424 * A ptr. to the anchor data or NULL.
425 * Note:
426 * anchor_words is an array that _only_ contains anchor data. Although
427 * it requires a bit more memory, it's worth it since it will be a fast
428 * lookup.
429 *****/
430 XmHTMLWord*
_XmHTMLGetAnchor(XmHTMLWidget html,int x,int y,XmHTMLImage * img)431 _XmHTMLGetAnchor(XmHTMLWidget html, int x, int y, XmHTMLImage *img)
432 {
433 XmHTMLWord *anchor_word = NULL;
434 int ys, xs;
435 register int i;
436
437 /* convert to absolute positions */
438 xs = x + HTML_ATTR(scroll_x);
439 ys = y + HTML_ATTR(scroll_y);
440
441 for(i = 0 ; i < HTML_ATTR(anchor_words); i++)
442 {
443 anchor_word = &(HTML_ATTR(anchors[i]));
444 if((xs >= anchor_word->x && xs<=(anchor_word->x+anchor_word->width)) &&
445 (ys>=anchor_word->y && ys<=(anchor_word->y+anchor_word->height)))
446 {
447 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetAnchor, anchor is: %s\n",
448 anchor_word->owner->anchor->href));
449
450 /* store line number */
451 anchor_word->owner->anchor->line = anchor_word->line;
452
453 /*****
454 * If we find an anchor, *and* it's an image *and* it references
455 * an imagemap, we must tell the caller to fetch the corresponding
456 * anchor from an imagemap using the found image.
457 *****/
458 if(anchor_word->type == OBJ_IMG &&
459 anchor_word->image->map_type != XmMAP_NONE)
460 {
461 img = anchor_word->image;
462 return(NULL);
463 }
464 img = NULL;
465 return(anchor_word);
466 }
467 }
468 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetAnchor, no match found\n"));
469
470 return(NULL);
471 }
472
473 /*****
474 * Name: _XmHTMLGetImageAnchor
475 * Return Type: XmHTMLAnchor*
476 * Description: determines if the given x and y positions lie upon an image
477 * that has an imagemap
478 * In:
479 * html: HTML widget to check
480 * x,y: position to validate
481 * list: list of images. If NULL the default list is used.
482 * Returns:
483 * A ptr. to the anchor data or NULL.
484 *****/
485 XmHTMLAnchor*
_XmHTMLGetImageAnchor(XmHTMLWidget html,int x,int y,XmHTMLImage * list)486 _XmHTMLGetImageAnchor(XmHTMLWidget html, int x, int y, XmHTMLImage *list)
487 {
488 XmHTMLImage *image = (list ? list : HTML_ATTR(images));
489 XmHTMLAnchor *anchor = NULL;
490 int ys, xs;
491 XmHTMLImageMap *imagemap = NULL;
492
493 /* convert to absolute position */
494 xs = x + HTML_ATTR(scroll_x);
495 ys = y + HTML_ATTR(scroll_y);
496
497 /* don't do this if we haven't got any imagemaps */
498 if(HTML_ATTR(image_maps) == NULL)
499 return(NULL);
500
501 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetImageAnchor, xs = %i, ys = %i\n",
502 xs, ys));
503
504 for(image = HTML_ATTR(images); image != NULL; image = image->next)
505 {
506 #ifdef DEBUG
507 if(image->owner)
508 {
509 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetImageAnchor, checking "
510 "%s, x = %i, y = %i\n", image->url, image->owner->x,
511 image->owner->y));
512 }
513 else
514 {
515 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetImageAnchor, checking %s "
516 "(no owner).", image->url));
517 }
518 #endif
519 if(image->owner && (xs >= image->owner->x &&
520 xs <= (image->owner->x + image->owner->width)) &&
521 (ys >= image->owner->y &&
522 ys <= (image->owner->y + image->owner->height)))
523 {
524 if(image->map_type != XmMAP_NONE)
525 {
526 if(image->map_type == XmMAP_SERVER)
527 {
528 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLGetImageAnchor"),
529 XMHTML_MSG_14);
530 return(NULL);
531 }
532 if((imagemap = _XmHTMLGetImagemap(html,
533 image->map_url)) != NULL)
534 {
535 if((anchor = _XmHTMLGetAnchorFromMap(html, x, y, image,
536 imagemap)) != NULL)
537 {
538 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetImageAnchor, "
539 "anchor is: %s\n", anchor->href));
540 return(anchor);
541 }
542 }
543
544 }
545 }
546 }
547 _XmHTMLFullDebug(1, ("XmHTML.c: _XmHTMLGetImageAnchor, no match found\n"));
548
549 return(NULL);
550 }
551
552 /*****
553 * Name: _XmHTMLOnImage
554 * Return Type: XmHTMLImage*
555 * Description: checks whether the given positions fall within an image
556 * In:
557 * html: XmHTMLWidget id
558 * x: pointer x-position
559 * y: pointer y-position
560 * Returns:
561 * The selected image if a match was found, NULL if not.
562 *****/
563 XmHTMLImage*
_XmHTMLOnImage(XmHTMLWidget html,int x,int y)564 _XmHTMLOnImage(XmHTMLWidget html, int x, int y)
565 {
566 XmHTMLImage *image;
567 int xs, ys;
568
569 /* convert to absolute position */
570 xs = x + HTML_ATTR(scroll_x);
571 ys = y + HTML_ATTR(scroll_y);
572
573 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLOnImage, xs = %i, ys = %i\n", xs, ys));
574
575 for(image = HTML_ATTR(images); image != NULL; image = image->next)
576 {
577 if(image->owner && (xs >= image->owner->x &&
578 xs <= (image->owner->x + image->owner->width)) &&
579 (ys >= image->owner->y &&
580 ys <= (image->owner->y + image->owner->height)))
581 {
582 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLOnImage, image selected: %s\n",
583 image->url));
584 return(image);
585 }
586 }
587 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLOnImage, no match found\n"));
588 return(NULL);
589 }
590
591 /*****
592 * Name: _XmHTMLReset
593 * Return Type: void
594 * Description: resets all non-persistent resources to their defaults
595 * In:
596 * html: XmHTMLWidget id
597 * free_img: true when images should be freed. This will only be True
598 * when the widget has received a new source.
599 * Returns:
600 * nothing
601 *****/
602 void
_XmHTMLReset(XmHTMLWidget html,Boolean free_img)603 _XmHTMLReset(XmHTMLWidget html, Boolean free_img)
604 {
605 /* reset some important vars */
606 HTML_ATTR(anchors) = (XmHTMLWord*)NULL;
607 HTML_ATTR(anchor_words) = 0;
608 HTML_ATTR(named_anchors) = (XmHTMLObjectTable*)NULL;
609 HTML_ATTR(num_named_anchors) = 0;
610 HTML_ATTR(anchor_current_cursor_element) = (XmHTMLAnchor*)NULL;
611 HTML_ATTR(armed_anchor) = (XmHTMLObjectTable*)NULL;
612 HTML_ATTR(current_anchor) = (XmHTMLObjectTable*)NULL;
613 HTML_ATTR(selected) = (XmHTMLAnchor*)NULL;
614 HTML_ATTR(selection) = (XmHTMLObjectTable*)NULL;
615 HTML_ATTR(select_start) = 0;
616 HTML_ATTR(select_end) = 0;
617 HTML_ATTR(scroll_x) = 0;
618 HTML_ATTR(scroll_y) = 0;
619 HTML_ATTR(formatted_width) = 1;
620 HTML_ATTR(formatted_height) = 1;
621 HTML_ATTR(paint_start) = (XmHTMLObjectTable*)NULL;
622 HTML_ATTR(paint_end) = (XmHTMLObjectTable*)NULL;
623 HTML_ATTR(paint_x) = 0;
624 HTML_ATTR(paint_y) = 0;
625 HTML_ATTR(paint_width) = 0;
626 HTML_ATTR(paint_height) = 0;
627 HTML_ATTR(scroll_x) = 0;
628 HTML_ATTR(scroll_y) = 0;
629 HTML_ATTR(top_line) = 0;
630 /* fix 02/26/97-01, kdh */
631 HTML_ATTR(paint_start) = (XmHTMLObjectTable*)NULL;
632 HTML_ATTR(paint_end) = (XmHTMLObjectTable*)NULL;
633 HTML_ATTR(nlines) = 0;
634
635 /* free the line table if it's present */
636 if(HTML_ATTR(line_table) != NULL)
637 free(HTML_ATTR(line_table));
638 HTML_ATTR(line_table) = (XmHTMLLineTable*)NULL;
639
640 /* Reset all colors */
641 HTML_ATTR(body_fg) = HTML_ATTR(body_fg_save);
642 HTML_ATTR(body_bg) = HTML_ATTR(body_bg_save);
643 HTML_ATTR(anchor_fg) = HTML_ATTR(anchor_fg_save);
644 HTML_ATTR(anchor_target_fg) = HTML_ATTR(anchor_target_fg_save);
645 HTML_ATTR(anchor_visited_fg) = HTML_ATTR(anchor_visited_fg_save);
646 HTML_ATTR(anchor_activated_fg) = HTML_ATTR(anchor_activated_fg_save);
647 HTML_ATTR(anchor_activated_bg) = HTML_ATTR(anchor_activated_bg_save);
648 HTML_ATTR(image_maps) = (XmHTMLImageMap*)NULL;
649
650 /* and reset image stuff if it was freed */
651 if(free_img)
652 {
653 /* must reset body_image as well since it also has been freed */
654 HTML_ATTR(body_image) = (XmHTMLImage*)NULL;
655 HTML_ATTR(images) = (XmHTMLImage*)NULL;
656 HTML_ATTR(body_image_url) = (String)NULL;
657 HTML_ATTR(alpha_buffer) = (AlphaPtr)NULL;
658 /* only reset when we aren't dithering */
659 if(HTML_ATTR(map_to_palette) == XmDISABLED)
660 HTML_ATTR(xcc) = (XCC)NULL;
661 }
662 }
663
664 /*****
665 * Name: _XmHTMLFreeExpendableResources
666 * Return Type: void
667 * Description: frees all non-persistent resources of a Widget
668 * In:
669 * html: XmHTMLWidget id
670 * free_img: true when images should be freed. This will only be True
671 * when the widget has received a new source.
672 * Returns:
673 * nothing
674 *****/
675 void
_XmHTMLFreeExpendableResources(XmHTMLWidget html,Boolean free_img)676 _XmHTMLFreeExpendableResources(XmHTMLWidget html, Boolean free_img)
677 {
678 /* Free anchor worddata */
679 if(HTML_ATTR(anchor_words))
680 free(HTML_ATTR(anchors));
681 HTML_ATTR(anchors) = (XmHTMLWord*)NULL;
682
683 /* Free named anchor data */
684 if(HTML_ATTR(num_named_anchors))
685 free(HTML_ATTR(named_anchors));
686 HTML_ATTR(named_anchors) = (XmHTMLObjectTable*)NULL;
687
688 /*****
689 * Always free imagemaps, anchor data becomes invalid!!
690 * (fix 09/17/97-02, kdh)
691 *****/
692 _XmHTMLFreeImageMaps(html);
693 HTML_ATTR(image_maps) = (XmHTMLImageMap*)NULL;
694
695 /* clear the images if we have to */
696 if(free_img)
697 {
698 /* Free all images (also clears xcc & alpha channel stuff) */
699 XmHTMLImageFreeAllImages((Widget)html);
700
701 /* must reset body_image as well since it also has been freed */
702 HTML_ATTR(body_image) = (XmHTMLImage*)NULL;
703 HTML_ATTR(images) = (XmHTMLImage*)NULL;
704 HTML_ATTR(delayed_creation) = False; /* no delayed image creation */
705 HTML_ATTR(alpha_buffer) = (AlphaPtr)NULL;
706 /* only reset when we aren't dithering */
707 if(HTML_ATTR(map_to_palette) == XmDISABLED)
708 {
709 XCCFree(HTML_ATTR(xcc));
710 HTML_ATTR(xcc) = (XCC)NULL;
711 }
712 }
713 else
714 {
715 /*****
716 * We need to orphan all images: the formatter will be called shortly
717 * after this routine returns and as a result of that the owner
718 * of each image will become invalid. Not orphanizing them would
719 * lead to a lot of image copying.
720 * Info structures with the XmIMAGE_DELAYED_CREATION bit need to
721 * propagate this info to their parent, or chances are that alpha
722 * channeling will *not* be redone when required.
723 * Must not forget to set the global delayed_creation flag or nothing
724 * will happen.
725 *****/
726 register XmHTMLImage *img;
727 for(img = HTML_ATTR(images); img != NULL; img = img->next)
728 {
729 img->owner = NULL; /* safety */
730 img->options |= IMG_ORPHANED;
731 if(!ImageInfoFreed(img) &&
732 ImageInfoDelayedCreation(img->html_image))
733 {
734 img->options |= IMG_DELAYED_CREATION;
735 HTML_ATTR(delayed_creation) = True;
736 }
737 }
738 }
739 }
740
741 /*****
742 * Name: _XmHTMLGetLineObject
743 * Return Type: void
744 * Description: get the object located at the given y position.
745 * In:
746 * html: XmHTMLWidget
747 * y_pos: current text y position.
748 * Returns:
749 * located element.
750 *****/
751 XmHTMLObjectTableElement
_XmHTMLGetLineObject(XmHTMLWidget html,int y_pos)752 _XmHTMLGetLineObject(XmHTMLWidget html, int y_pos)
753 {
754 register XmHTMLObjectTableElement tmp = NULL;
755 int i;
756
757 /*
758 * y_pos given must fall in the bounding box of an element.
759 * We try to be a little bit smart here:
760 * If we have a paint engine end and it's y position is below the
761 * requested position, walk forwards until we find a match.
762 * If we have a paint engine start and it's y position is below the
763 * requested position, walk forwards. If it's above the requested position,
764 * walk backwards. We are always bound to find a matching element.
765 */
766 if(HTML_ATTR(paint_end) || HTML_ATTR(paint_start))
767 {
768 /* located above paint engine end, walk forwards */
769 if(HTML_ATTR(paint_end) && HTML_ATTR(paint_end->y) < y_pos)
770 {
771 for(tmp = HTML_ATTR(paint_end); tmp != NULL; tmp = tmp->next)
772 if(y_pos >= tmp->y && y_pos < tmp->y + tmp->height)
773 break;
774 }
775 /* not found or no paint engine end */
776 else if(HTML_ATTR(paint_start))
777 {
778 /* located above paint engine start, walk forwards */
779 if(HTML_ATTR(paint_start->y) < y_pos)
780 {
781 for(tmp = HTML_ATTR(paint_start); tmp != NULL; tmp = tmp->next)
782 if(y_pos >= tmp->y && y_pos < tmp->y + tmp->height)
783 break;
784 }
785 /* located under paint engine start, walk backwards */
786 else
787 {
788 for(tmp = HTML_ATTR(paint_start); tmp != NULL; tmp = tmp->prev)
789 if(y_pos >= tmp->y && y_pos < tmp->y + tmp->height)
790 break;
791 }
792 }
793 }
794 /* neither paint engine start or end */
795 else
796 {
797 /* sanity */
798 if(HTML_ATTR(line_table) == NULL)
799 {
800 _XmHTMLDebug(1, ("private.c: _XmHTMLGetLineObject"
801 " No line table present!\n"));
802 return(NULL);
803 }
804
805 i = 0;
806 while(i < HTML_ATTR(nlines))
807 {
808 if(HTML_ATTR(line_table)[i].y >= y_pos &&
809 HTML_ATTR(line_table)[i].used)
810 return(HTML_ATTR(line_table)[i].start);
811 i++;
812 }
813 }
814
815 /* top or bottom element */
816 if(tmp == NULL || tmp->prev == NULL)
817 {
818 /* bottom element */
819 if(tmp == NULL)
820 return(HTML_ATTR(formatted));
821 /* top element otherwise */
822 return(NULL);
823 }
824 else if(tmp->y == y_pos)
825 return(tmp);
826
827 /*****
828 * Finetuning: start searching the linetable using the line number
829 * of the matched object as starting point.
830 *****/
831
832 /* sanity */
833 if(HTML_ATTR(line_table) == NULL)
834 {
835 _XmHTMLDebug(1, ("private.c: _XmHTMLGetLineObject"
836 " No line table present!\n"));
837 return(tmp);
838 }
839
840 i = tmp->line;
841
842 if(HTML_ATTR(line_table)[i].y < y_pos)
843 {
844 while(i < HTML_ATTR(nlines))
845 {
846 if(HTML_ATTR(line_table)[i].y >= y_pos &&
847 HTML_ATTR(line_table)[i].used)
848 return(HTML_ATTR(line_table)[i].start);
849 i++;
850 }
851 }
852 else
853 {
854 while(i)
855 {
856 if(HTML_ATTR(line_table)[i].y >= y_pos &&
857 HTML_ATTR(line_table)[i].used)
858 return(HTML_ATTR(line_table)[i].start);
859 i--;
860 }
861 }
862 return(NULL);
863 }
864
865 /*****
866 * Name: _XmHTMLSetCurrentLineNumber
867 * Return Type: void
868 * Description: get & set the linenumber of the line at the top of the
869 * working area.
870 * In:
871 * html: XmHTMLWidget
872 * y_pos: current text y position.
873 * Returns:
874 * nothing, but the top_line field of the htmlRec is updated.
875 *****/
876 void
_XmHTMLSetCurrentLineNumber(XmHTMLWidget html,int y_pos)877 _XmHTMLSetCurrentLineNumber(XmHTMLWidget html, int y_pos)
878 {
879 XmHTMLObjectTableElement tmp;
880
881 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLSetCurrentLineNumber, y_pos = %i\n",
882 y_pos));
883
884 if((tmp = _XmHTMLGetLineObject(html, y_pos)) != NULL)
885 {
886
887 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLSetCurrentLineNumber, object found, "
888 "y_pos = %i, linenumber = %i\n", tmp->y, tmp->line));
889
890 /* set line number for the found object */
891 HTML_ATTR(top_line) = tmp->line;
892
893 /*****
894 * If the current element has got more than one word in it, and these
895 * words span accross a number of lines, adjust the linenumber.
896 *****/
897 if(tmp->n_words > 1 && tmp->words[0].y != tmp->words[tmp->n_words-1].y)
898 {
899 int i;
900 for(i = 0 ; i < tmp->n_words && tmp->words[i].y < y_pos; i++);
901 if(i != tmp->n_words)
902 HTML_ATTR(top_line) = tmp->words[i].line;
903 }
904 }
905 else
906 HTML_ATTR(top_line) = 0;
907
908 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLSetCurrentLineNumber, top_line = %i\n",
909 HTML_ATTR(top_line)));
910 }
911
912 /*****
913 * Name: _XmHTMLCheckMaxColorSetting
914 * Return Type: void
915 * Description: checks value of the XmNmaxImageColors resource against
916 * maximum number of colors allowed for this display.
917 * In:
918 * html: XmHTMLWidget
919 * Returns:
920 * nothing;
921 *****/
922 void
_XmHTMLCheckMaxColorSetting(XmHTMLWidget html)923 _XmHTMLCheckMaxColorSetting(XmHTMLWidget html)
924 {
925 int max_colors;
926
927 /* check for an XCC */
928 if(HTML_ATTR(xcc) == NULL)
929 _XmHTMLCheckXCC(html);
930
931 /* get maximum allowable colors */
932 max_colors = XCCGetNumColors(HTML_ATTR(xcc));
933
934 /* limit to 256 colors */
935 if(max_colors > XmHTML_MAX_IMAGE_COLORS)
936 max_colors = XmHTML_MAX_IMAGE_COLORS;
937
938 /* verify */
939 if(HTML_ATTR(max_image_colors) > max_colors)
940 {
941 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLCheckMaxColorSetting"),
942 XMHTML_MSG_15, HTML_ATTR(max_image_colors), max_colors,
943 max_colors);
944 HTML_ATTR(max_image_colors) = max_colors;
945 }
946 /* plop maximum colors in */
947 else if(HTML_ATTR(max_image_colors) == 0)
948 HTML_ATTR(max_image_colors) = max_colors;
949 }
950
951 /*****
952 * Name: _XmHTMLGetAnchorByName
953 * Return Type: XmHTMLObjectTableElement
954 * Description: returns the named anchor data.
955 * In:
956 * html: XmHTMLWidget
957 * anchor: anchor to locate, with a leading hash sign.
958 * Returns:
959 * anchor data upon success, NULL on failure.
960 *****/
961 XmHTMLObjectTableElement
_XmHTMLGetAnchorByName(XmHTMLWidget html,String anchor)962 _XmHTMLGetAnchorByName(XmHTMLWidget html, String anchor)
963 {
964 XmHTMLObjectTableElement anchor_data;
965 int i;
966 String chPtr = NULL;
967
968 /* see if it is indeed a named anchor */
969 if(!anchor || !*anchor || anchor[0] != '#')
970 return(NULL); /* fix 02/03/97-04, kdh */
971
972 /* we start right after the leading hash sign */
973 chPtr = &anchor[1];
974
975 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByName Start\n"));
976
977 for(i = 0 ; i < HTML_ATTR(num_named_anchors); i++)
978 {
979 anchor_data = &(HTML_ATTR(named_anchors[i]));
980 if(anchor_data->anchor && anchor_data->anchor->name &&
981 !strcmp(anchor_data->anchor->name, chPtr))
982 {
983 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByName End, "
984 "match found.\n"));
985 return(anchor_data);
986 }
987 }
988 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByName End\n"));
989 return(NULL);
990 }
991
992 /*****
993 * Name: _XmHTMLGetAnchorByValue
994 * Return Type: XmHTMLObjectTableElement
995 * Description: returns the named anchor data.
996 * In:
997 * w: XmHTMLWidget
998 * anchor_id: internal anchor id.
999 * Returns:
1000 * anchor data upon success, NULL on failure.
1001 *****/
1002 XmHTMLObjectTableElement
_XmHTMLGetAnchorByValue(XmHTMLWidget html,int anchor_id)1003 _XmHTMLGetAnchorByValue(XmHTMLWidget html, int anchor_id)
1004 {
1005 XmHTMLObjectTableElement anchor_data;
1006 int i;
1007 String func = "_XmHTMLGetAnchorByValue";
1008
1009 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByValue Start\n"));
1010
1011 /* sanity */
1012 if(anchor_id < 0 || anchor_id >= HTML_ATTR(num_named_anchors))
1013 {
1014 _XmHTMLWarning(__WFUNC__(html, func), XMHTML_MSG_21,
1015 "Invalid id", func);
1016 return(NULL);
1017 }
1018
1019 /* this should always match */
1020 anchor_data = &(HTML_ATTR(named_anchors[anchor_id]));
1021 if(anchor_data->id == anchor_id)
1022 return(anchor_data);
1023
1024 /* hmm, something went wrong, search the whole list of named anchors */
1025 _XmHTMLWarning(__WFUNC__(html, func),
1026 XMHTML_MSG_18, anchor_id);
1027
1028 for(i = 0 ; i < HTML_ATTR(num_named_anchors); i++)
1029 {
1030 anchor_data = &(HTML_ATTR(named_anchors[i]));
1031 if(anchor_data->id == anchor_id)
1032 {
1033 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByValue End, "
1034 "match found.\n"));
1035 return(anchor_data);
1036 }
1037 }
1038 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLGetAnchorByValue End\n"));
1039 return(NULL);
1040 }
1041
1042 /*****
1043 * Name: _XmHTMLVerticalPosToLine
1044 * Return Type: int
1045 * Description: translates a vertical position to the current line number
1046 * in the currently displayed document.
1047 * In:
1048 * html: XmHTMLWidget id;
1049 * y: absolute document y position.
1050 * Returns:
1051 * line number of the object found at the given position. nlines if not found.
1052 *****/
1053 int
_XmHTMLVerticalPosToLine(XmHTMLWidget html,int y)1054 _XmHTMLVerticalPosToLine(XmHTMLWidget html, int y)
1055 {
1056 XmHTMLObjectTableElement tmp;
1057
1058 /* sanity check */
1059 if(!HTML_ATTR(formatted))
1060 return(0);
1061
1062 if((tmp = _XmHTMLGetLineObject(html, y)) != NULL)
1063 {
1064
1065 _XmHTMLDebug(1, ("XmHTML.c: VerticalPosToLine, object found, "
1066 "y_pos = %i, linenumber = %i\n", tmp->y, tmp->line));
1067
1068 /*
1069 * If the current element has got more than one word in it, and these
1070 * words span accross a number of lines, adjust the linenumber.
1071 */
1072 if(tmp->n_words > 1 && tmp->words[0].y != tmp->words[tmp->n_words-1].y)
1073 {
1074 int i;
1075 for(i = 0 ; i < tmp->n_words && tmp->words[i].y < y; i++);
1076 if(i != tmp->n_words)
1077 return(tmp->words[i].line);
1078 else
1079 return(tmp->line);
1080 }
1081 else
1082 return(tmp->line);
1083 }
1084 return(0);
1085 }
1086
1087 /*****
1088 * Name: _XmHTMLScrollToLine
1089 * Return Type: void
1090 * Description: scrolls the widget to the given line number.
1091 * In:
1092 * html: XmHTMLWidget id
1093 * line: line number to scroll to.
1094 * Returns:
1095 * nothing.
1096 *****/
1097 void
_XmHTMLScrollToLine(XmHTMLWidget html,int line)1098 _XmHTMLScrollToLine(XmHTMLWidget html, int line)
1099 {
1100 XmHTMLObjectTableElement tmp = NULL;
1101
1102 /* use the cast so negative line numbers are also allowed */
1103 if(line > (int)(HTML_ATTR(nlines)))
1104 {
1105 int value;
1106
1107 _XmHTMLDebug(1, ("XmHTML.c: ScrollToLine, "
1108 "calling _XmHTMLMoveToPos\n"));
1109
1110 HTML_ATTR(top_line) = HTML_ATTR(nlines);
1111 value = HTML_ATTR(formatted_height);
1112
1113 /* fix 01/30/97-04, kdh */
1114 _XmHTMLAdjustVerticalScrollValue(HTML_ATTR(vsb), &value);
1115
1116 _XmHTMLMoveToPos(HTML_ATTR(vsb), html, value);
1117 return;
1118 }
1119 if(line <= 0)
1120 {
1121 HTML_ATTR(top_line) = 0;
1122 _XmHTMLDebug(1, ("XmHTML.c: ScrollToLine, "
1123 "calling _XmHTMLMoveToPos\n"));
1124 _XmHTMLMoveToPos(HTML_ATTR(vsb), html, 0);
1125 return;
1126 }
1127
1128 /* sanity */
1129 if(HTML_ATTR(line_table) == NULL)
1130 {
1131 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLScrollToLine"),
1132 "No line table present!");
1133 return;
1134 }
1135
1136 /* make sure we get a match! */
1137 while(HTML_ATTR(line_table)[line].used == False &&
1138 line < HTML_ATTR(nlines))
1139 line++;
1140
1141 if(line == HTML_ATTR(nlines))
1142 {
1143 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLScrollToLine"),
1144 "Failed to detect requested line number (%i)", line);
1145 return;
1146 }
1147
1148 tmp = HTML_ATTR(line_table)[line].start;
1149
1150 /* get vertical position */
1151 if(tmp)
1152 {
1153 int i, value; /* position to scroll to */
1154
1155 /* we might have gone one object to far. Check and adjust */
1156 tmp = (line != tmp->line ? (tmp->prev ? tmp->prev : tmp) : tmp);
1157
1158 value = tmp->y;
1159 HTML_ATTR(top_line) = tmp->line;
1160
1161 /*
1162 * Not exactly the requested line. Now check the line numbers of
1163 * the text inside this object. We need to subtract the height of this
1164 * object if we want to have it displayed properly.
1165 */
1166 if(tmp->line != line)
1167 {
1168 if(tmp->n_words)
1169 {
1170 /* fix 11/11/97-01, dbl */
1171 for(i = 0; i < tmp->n_words && line > tmp->words[i].line;
1172 i++);
1173 /* if found, we need to take y position of the previous word */
1174 if(i != tmp->n_words && i != 0)
1175 {
1176 HTML_ATTR(top_line) = tmp->words[i-1].line;
1177 value = tmp->words[i-1].y - tmp->words[i-1].height;
1178 }
1179 }
1180 }
1181 _XmHTMLDebug(1, ("XmHTML.c: ScrollToLine, "
1182 "requested line: %i, lineno found: %i, y_pos: %i\n",
1183 line, tmp->line, value));
1184
1185 /* fix 01/30/97-04, kdh */
1186 _XmHTMLAdjustVerticalScrollValue(HTML_ATTR(vsb), &value);
1187
1188 _XmHTMLMoveToPos(HTML_ATTR(vsb), html, value);
1189 }
1190 else
1191 {
1192 _XmHTMLDebug(1, ("XmHTML.c: ScrollToLine, "
1193 "failed to detect requested line number!\n"));
1194 }
1195 }
1196
1197 /*****
1198 * Name: _XmHTMLDestroyPhaseZero
1199 * Return Type: void
1200 * Description: discard all toolkit independent resources
1201 * In:
1202 * html: XmHTMLWidget id being destroyed
1203 * Returns:
1204 * nothing
1205 *****/
1206 void
_XmHTMLDestroyPhaseZero(XmHTMLWidget html)1207 _XmHTMLDestroyPhaseZero(XmHTMLWidget html)
1208 {
1209 ToolkitAbstraction *tka = HTML_ATTR(tka);
1210
1211 /* First kill any outstanding PLC's */
1212 _XmHTMLKillPLCCycler(html);
1213
1214 /* release event database */
1215 _XmHTMLEventFreeDatabase(html, html);
1216
1217 /* Free list of parsed HTML elements */
1218 HTML_ATTR(elements) = _XmHTMLparseHTML(html, HTML_ATTR(elements), NULL,
1219 NULL);
1220
1221 /* Free list of formatted HTML elements */
1222 _XmHTMLformatObjects(html, html);
1223
1224 /* Free list of form data */
1225 _XmHTMLFreeForm(html, HTML_ATTR(form_data));
1226 HTML_ATTR(form_data) = (XmHTMLFormData*)NULL;
1227
1228 /* free all non-persitent resources and destroy the images */
1229 _XmHTMLFreeExpendableResources(html, True);
1230
1231 /*****
1232 * Free list of frames. It is important that the images are destroyed
1233 * *before* the frames themselves get destroyed: frames can also have
1234 * images, and destroying the frame before destroying the image data
1235 * causes havoc. _XmHTMLDestroyFrames invokes XtDestroyWidget to destroy
1236 * each of XmHTML's frame childs, which invokes this routine and so on.
1237 *****/
1238 if(HTML_ATTR(nframes))
1239 _XmHTMLDestroyFrames(html, HTML_ATTR(nframes));
1240
1241 /* free all fonts for this widget's instance */
1242 _XmHTMLUnloadFonts(html);
1243
1244 /* free cursors */
1245 if(HTML_ATTR(anchor_cursor) != None)
1246 tka->FreeCursor(tka->dpy, HTML_ATTR(anchor_cursor));
1247
1248 /* Free GC's */
1249 if(HTML_ATTR(gc))
1250 tka->FreeGC(tka->dpy, HTML_ATTR(gc));
1251 if(HTML_ATTR(bg_gc))
1252 tka->FreeGC(tka->dpy, HTML_ATTR(bg_gc));
1253 }
1254
1255 /*****
1256 * Name: _XmHTMLCheckGC
1257 * Return Type: void
1258 * Description: creates a Graphics Context to be used for rendering
1259 * In:
1260 * html: XmHTMLWidget
1261 * Returns:
1262 * nothing, but a GC is created and stored in the widget's internal data
1263 * structure. If background images are allowed, a seperate GC is created
1264 * which is used in PaintBackground to do tiling of the background with an
1265 * image.
1266 *****/
1267 void
_XmHTMLCheckGC(XmHTMLWidget html)1268 _XmHTMLCheckGC(XmHTMLWidget html)
1269 {
1270 ToolkitAbstraction *tka = HTML_ATTR(tka);
1271
1272 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckGC Start\n"));
1273
1274 /* sanity check, we *must* have a window if we want to have a gc!! */
1275 if(!tka->IsRealized((Widget)html) || tka->win == None)
1276 return;
1277
1278 /* main gc */
1279 if(HTML_ATTR(gc) == NULL)
1280 {
1281 HTML_ATTR(gc) = tka->CreateGC(tka->dpy, tka->win, 0, NULL);
1282 tka->SetFunction(tka->dpy, HTML_ATTR(gc), tka->gc_func[GC_GXcopy]);
1283 tka->SetForeground(tka->dpy, HTML_ATTR(gc), MGR_ATTR(foreground));
1284 tka->SetBackground(tka->dpy, HTML_ATTR(gc),
1285 CORE_ATTR(background_pixel));
1286
1287 XmHTMLTkaRecomputeColors(html, HTML_ATTR(body_bg));
1288
1289 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckGC, gc created\n"));
1290 }
1291 /* background image gc */
1292 if(HTML_ATTR(body_images_enabled) && HTML_ATTR(bg_gc) == NULL)
1293 {
1294 HTML_ATTR(bg_gc) = tka->CreateGC(tka->dpy, tka->win, 0, NULL);
1295 tka->CopyGC(tka->dpy, HTML_ATTR(gc), 0xFFFF, HTML_ATTR(bg_gc));
1296 }
1297
1298 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckGC End\n"));
1299 }
1300
1301 /*****
1302 * Name: _XmHTMLLayout
1303 * Return Type: void
1304 * Description: main layout algorithm.
1305 * computes text layout and configures the scrollbars.
1306 * Also handles image recreation.
1307 * In:
1308 * html: widget to layout
1309 * Returns:
1310 * nothing
1311 *****/
1312 void
_XmHTMLLayout(XmHTMLWidget html)1313 _XmHTMLLayout(XmHTMLWidget html)
1314 {
1315 XmHTMLObjectTableElement curr_ele = NULL;
1316
1317 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLLayout Start\n"));
1318
1319 /* set blocking flag */
1320 HTML_ATTR(in_layout) = True;
1321
1322 /* remember current vertical position if we have been scrolled */
1323 if(HTML_ATTR(scroll_y))
1324 curr_ele = _XmHTMLGetLineObject(html, HTML_ATTR(scroll_y));
1325
1326 /* make a resize request if we have to do auto-sizing in either direction */
1327 if(HTML_ATTR(resize_width) || HTML_ATTR(resize_height))
1328 _XmHTMLAutoSizeWidget(html);
1329 else
1330 _XmHTMLComputeLayout(html);
1331
1332 /* set new vertical scrollbar positions */
1333 if(curr_ele != NULL)
1334 HTML_ATTR(scroll_y) = curr_ele->y;
1335 else
1336 HTML_ATTR(scroll_y) = 0;
1337
1338 /* configure the scrollbars, will also resize work_area */
1339 _XmHTMLCheckScrollBars(html);
1340
1341 HTML_ATTR(in_layout) = False;
1342 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLLayout End\n"));
1343 return;
1344 }
1345
1346 /*****
1347 * Name: _XmHTMLResize
1348 * Return Type: void
1349 * Description: xmHTMLWidgetClass resize method.
1350 * In:
1351 * w: resized widget.
1352 * Returns:
1353 * nothing
1354 *****/
1355 void
_XmHTMLResize(Widget w)1356 _XmHTMLResize(Widget w)
1357 {
1358 Boolean do_expose;
1359 XmHTMLWidget html = (XmHTMLWidget)w;
1360 int foo, vsb_width;
1361 ToolkitAbstraction *tka = HTML_ATTR(tka);
1362
1363 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize Start\n"));
1364
1365 /* No needless resizing */
1366 if(!tka->IsRealized(w))
1367 {
1368 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize end, widget not "
1369 "realized.\n"));
1370 return;
1371 }
1372
1373 if(HTML_ATTR(in_layout))
1374 {
1375 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize end, layout flag is set.\n"));
1376 return;
1377 }
1378
1379 _XmHTMLGetScrollDim(html, &foo, &vsb_width);
1380
1381 /* No change in size, return */
1382 if((CORE_ATTR(height) == HTML_ATTR(work_height)) &&
1383 (CORE_ATTR(width) == (HTML_ATTR(work_width) + HTML_ATTR(margin_width) +
1384 vsb_width)))
1385 {
1386 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize End, no change in size\n"));
1387 return;
1388 }
1389
1390 /*
1391 * Check if we have to do layout and generate an expose event.
1392 * When the widget shrinks, X does not generate an expose event.
1393 * We want to recompute layout and generate an expose event when the
1394 * width changes.
1395 * When the height increases, we only want to generate a partial
1396 * exposure (this gets handled in Redisplay).
1397 */
1398 do_expose = (CORE_ATTR(width) != (HTML_ATTR(work_width) +
1399 HTML_ATTR(margin_width) + vsb_width));
1400
1401 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize, new window dimensions: %ix%i.\n",
1402 CORE_ATTR(width) - HTML_ATTR(margin_width), HTML_ATTR(work_height)));
1403 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLResize, generating expose event : %s.\n",
1404 (do_expose ? "yes" : "no")));
1405
1406 /* Clear current visible text */
1407 if(do_expose)
1408 {
1409 /*
1410 * save new height & width of visible area.
1411 * subtract margin_width once to minimize number of calcs in
1412 * the paint routines: every thing rendered starts at an x position
1413 * of margin_width.
1414 */
1415 HTML_ATTR(work_width) = CORE_ATTR(width) - HTML_ATTR(margin_width) -
1416 vsb_width;
1417 HTML_ATTR(work_height)= CORE_ATTR(height);
1418
1419 /* Recompute layout */
1420 _XmHTMLLayout(html);
1421
1422 /* Clear current text area and generate an expose event */
1423 _XmHTMLClearArea(html, 0, 0, CORE_ATTR(width), CORE_ATTR(height));
1424 }
1425 /* change in height */
1426 else
1427 {
1428 /*
1429 * Get new start & end points for the paint engine
1430 * We have two cases: shrink or stretch.
1431 * When stretched, we generate an exposure event for the added
1432 * area and let DrawRedisplay figure it out. If shrunk, adjust
1433 * end point for the paint engine.
1434 */
1435
1436 /* Window has been stretched */
1437 if(HTML_ATTR(work_height) < CORE_ATTR(height))
1438 {
1439 /*
1440 * formatted_height has some formatting offsets in it. Need
1441 * to subtract them first.
1442 */
1443 int max = HTML_ATTR(formatted_height) - HTML_ATTR(margin_height) -
1444 HTML_ATTR(default_font)->descent;
1445 /*
1446 * If the stretch is so large that the entire text will fit
1447 * in the new window height, remove the scrollbars by resetting
1448 * the vertical scrollbar position.
1449 */
1450 if(CORE_ATTR(height) > max)
1451 HTML_ATTR(scroll_y) = 0;
1452
1453 /* save new height */
1454 HTML_ATTR(work_height) = CORE_ATTR(height);
1455
1456 /* reset scrollbars (this will also resize the work_area) */
1457 _XmHTMLCheckScrollBars(html);
1458
1459 /*
1460 * just clear the entire area. Will generate a double exposure
1461 * but everything will be painted as it should.
1462 */
1463 _XmHTMLClearArea(html, 0, 0, CORE_ATTR(width), CORE_ATTR(height));
1464 }
1465 /* window has been shrunk */
1466 else
1467 {
1468 XmHTMLObjectTable *start, *end;
1469 int y;
1470
1471 /* get new y maximum */
1472 y = HTML_ATTR(scroll_y) + CORE_ATTR(height);
1473
1474 /* Starting point is end of previous stream */
1475 start = (HTML_ATTR(paint_end) == NULL ? HTML_ATTR(formatted):
1476 HTML_ATTR(paint_end));
1477
1478 /* Walk backwards until we reach the desired height */
1479 for(end = start; end != NULL && y >= end->y; end = end->prev);
1480
1481 /* save end point */
1482 HTML_ATTR(paint_end) = end;
1483
1484 /* save new height */
1485 HTML_ATTR(work_height) = CORE_ATTR(height);
1486
1487 /* reset scrollbars (this will also resize the work_area) */
1488 _XmHTMLCheckScrollBars(html);
1489
1490 /* no need to paint */
1491 }
1492 }
1493 /* resize XmHTML's frame childs */
1494 if(HTML_ATTR(nframes))
1495 {
1496 _XmHTMLDebug(1, ("XmHTML.c: Resize, calling ReconfigureFrames\n"));
1497 _XmHTMLReconfigureFrames(html);
1498 }
1499
1500 _XmHTMLSetScrollBars(html);
1501
1502 _XmHTMLDebug(1, ("XmHTML.c: Resize End\n"));
1503
1504 return;
1505 }
1506
1507 /*****
1508 * Name: _XmHTMLClearArea
1509 * Return Type: void
1510 * Description: XClearArea wrapper. Does form component updating as well.
1511 * In:
1512 * html: XmHTMLWidget id;
1513 * x,y: upper left corner of region to be updated;
1514 * width: width of region;
1515 * height: height of region;
1516 * Returns:
1517 *
1518 *****/
1519 void
_XmHTMLClearArea(XmHTMLWidget html,int x,int y,int width,int height)1520 _XmHTMLClearArea(XmHTMLWidget html, int x, int y, int width, int height)
1521 {
1522 ToolkitAbstraction *tka = HTML_ATTR(tka);
1523
1524 /*****
1525 * Sanity check, we must have a window before we can clear anything.
1526 * Could happen when XmNmappedWhenManaged has been set to False.
1527 *****/
1528 if(!tka->IsRealized((Widget)html) || tka->win == None)
1529 return;
1530
1531 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLClearArea Start, x: %i, y: %i, width: "
1532 "%i height: %i.\n", x, y, width, height));
1533
1534 /* first scroll form widgets if we have them */
1535 if(HTML_ATTR(form_data))
1536 {
1537 _XmHTMLScrollForm(html);
1538 tka->ClearArea(tka->dpy, tka->win, x, y, width, height, False);
1539 _XmHTMLRefresh(html, x, y, width, height);
1540
1541 /*****
1542 * If we've got a form but no clipmask, fallback to less-smooth
1543 * scrolling
1544 *****/
1545 #if 0
1546 if(HTML_ATTR(form_data) && HTML_ATTR(form_data)->can_clip == False)
1547 _XmHTMLRaiseFormWidgets(html);
1548 #endif
1549 }
1550 else
1551 tka->ClearArea(tka->dpy, tka->win, x, y, width, height, True);
1552
1553 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLClearArea End.\n"));
1554 }
1555
1556 /*****
1557 * Name: _XmHTMLCheckXCC
1558 * Return Type: void
1559 * Description: creates an XCC for the given XmHTMLWidget if one hasn't been
1560 * allocated yet.
1561 * In:
1562 * html: XmHTMLWidget id;
1563 * Returns:
1564 * nothing
1565 *****/
1566 void
_XmHTMLCheckXCC(XmHTMLWidget html)1567 _XmHTMLCheckXCC(XmHTMLWidget html)
1568 {
1569 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckXCC Start\n"));
1570
1571 /*
1572 * CheckXCC is called each time an image is loaded, so it's quite
1573 * usefull if we have a GC around by the time the widget is being
1574 * mapped to the display.
1575 * Our SubstructureNotify event handler can fail in some cases leading to
1576 * a situation where we don't have a GC when images are about to be
1577 * rendered (especially background images can cause a problem, they
1578 * are at the top of the text).
1579 */
1580 _XmHTMLCheckGC(html);
1581
1582 /*
1583 * Create an XCC.
1584 * XmHTML never decides whether or not to use a private or standard
1585 * colormap. A private colormap can be supplied by setting it on the
1586 * widget's parent, we know how to deal with that.
1587 */
1588 if(!HTML_ATTR(xcc))
1589 {
1590 VISUAL *visual = NULL;
1591 COLORMAP cmap = TkaGetColormap(html);
1592
1593 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckXCC: creating an XCC\n"));
1594
1595 /* get a visual, always returns a good one so no check required */
1596 visual = XCCGetParentVisual((Widget)html);
1597
1598 /* create an xcc for this widget */
1599 HTML_ATTR(xcc) = XCCCreate((Widget)html, visual, cmap);
1600 }
1601 _XmHTMLDebug(1, ("XmHTML.c: _XmHTMLCheckXCC End\n"));
1602 }
1603
1604 /*****
1605 * Name: _XmHTMLMoveToPos
1606 * Return Type: void
1607 * Description: scroll the working area with the given value
1608 * In:
1609 * w: originator
1610 * html: XmHTMLWidget
1611 * value: position to scroll to
1612 * Returns:
1613 * nothing
1614 *****/
1615 void
_XmHTMLMoveToPos(Widget w,XmHTMLWidget html,int value)1616 _XmHTMLMoveToPos(Widget w, XmHTMLWidget html, int value)
1617 {
1618 int inc, x, y, width, height;
1619 ToolkitAbstraction *tka = HTML_ATTR(tka);
1620 int vsb_width = 0, hsb_height = 0;
1621 XmHTMLFormData *form = HTML_ATTR(form_data);
1622
1623 /* sanity check */
1624 if(value < 0)
1625 return;
1626
1627 /* default exposure region */
1628 x = y = 0;
1629 width = CORE_ATTR(width);
1630 height = CORE_ATTR(height);
1631
1632 /*
1633 * need to adjust slider position since we may not be called from
1634 * the scrollbar callback handler.
1635 */
1636 TkaScrollbarSliderSetPosition(w, value);
1637
1638 /*****
1639 * If we've got a form but no clipmask, fallback to less-smooth
1640 * scrolling
1641 *****/
1642 #if 0
1643 if(form && form->can_clip == False)
1644 LowerFormWidgets(html);
1645 #endif
1646
1647 /* vertical scrolling */
1648 if(w == HTML_ATTR(vsb))
1649 {
1650 /*
1651 * clicking on the slider causes activation of the scrollbar
1652 * callbacks. Since there is no real movement, just return.
1653 * Not doing this will cause an entire redraw of the window.
1654 */
1655 if(value == HTML_ATTR(scroll_y))
1656 return; /* fix 01/20/97-01 kdh */
1657
1658 /* save line number */
1659 _XmHTMLSetCurrentLineNumber(html, value);
1660
1661 /* moving down (text moving up) */
1662 if(value > HTML_ATTR(scroll_y))
1663 {
1664 inc = value - HTML_ATTR(scroll_y);
1665
1666 /* save new value */
1667 HTML_ATTR(scroll_y) = value;
1668
1669 /* save new paint engine start */
1670 HTML_ATTR(paint_start) = HTML_ATTR(paint_end);
1671
1672 /* small increment */
1673 if(inc < HTML_ATTR(work_height))
1674 {
1675 /*****
1676 * See if we have a hsb. If we have one, we need to add
1677 * the height of the hsb to the region requiring updating.
1678 *****/
1679 if(HTML_ATTR(needs_hsb))
1680 #ifdef NO_XLIB_ILLEGAL_ACCESS
1681 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1682 #else
1683 hsb_height = ATTR_CORE(HTML_ATTR(hsb), height);
1684 #endif
1685 /****
1686 * Set clipmask for proper form scrolling only if we're
1687 * in range
1688 *****/
1689 if(form && form->can_clip)
1690 {
1691 int xs = form->x - HTML_ATTR(scroll_x);
1692 int ys = form->y - value;
1693
1694 if(ys + form->height < 0 || ys > HTML_ATTR(work_height) ||
1695 xs + form->width < 0 || xs > HTML_ATTR(work_width))
1696 ;
1697 else
1698 {
1699 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), form->clip);
1700 tka->SetClipOrigin(tka->dpy, HTML_ATTR(gc), xs, ys);
1701 }
1702 }
1703
1704 /* copy visible part upward */
1705 tka->CopyArea(tka->dpy, tka->win, tka->win, HTML_ATTR(gc), 0,
1706 inc, HTML_ATTR(work_width) + HTML_ATTR(margin_width),
1707 HTML_ATTR(work_height) - inc - hsb_height, 0, 0);
1708
1709 if(form)
1710 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), None);
1711
1712 /* clear area below */
1713 x = 0;
1714 y = HTML_ATTR(work_height) - inc - hsb_height;
1715 width = CORE_ATTR(width);
1716 height = inc + hsb_height;
1717 }
1718 /* large increment, use default area */
1719 }
1720 /* moving up (text moving down) */
1721 else
1722 {
1723 inc = HTML_ATTR(scroll_y) - value;
1724
1725 /* save new value */
1726 HTML_ATTR(scroll_y) = value;
1727
1728 /* small increment */
1729 if(inc < HTML_ATTR(work_height))
1730 {
1731 /****
1732 * Set clipmask for proper form scrolling only if we're
1733 * in range
1734 *****/
1735 if(form && form->can_clip)
1736 {
1737 int xs = form->x - HTML_ATTR(scroll_x);
1738 int ys = form->y - value;
1739
1740 if(ys + form->height < 0 || ys > HTML_ATTR(work_height) ||
1741 xs + form->width < 0 || xs > HTML_ATTR(work_width))
1742 ;
1743 else
1744 {
1745 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), form->clip);
1746 tka->SetClipOrigin(tka->dpy, HTML_ATTR(gc), xs, ys);
1747 }
1748 }
1749
1750 /* copy area down */
1751 tka->CopyArea(tka->dpy, tka->win, tka->win, HTML_ATTR(gc), 0, 0,
1752 HTML_ATTR(work_width) + HTML_ATTR(margin_width),
1753 HTML_ATTR(work_height) - inc, 0, inc);
1754
1755 /* save paint engine end */
1756 HTML_ATTR(paint_end) = HTML_ATTR(paint_start);
1757
1758 if(form)
1759 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), None);
1760
1761 /* clear area above */
1762 x = y = 0;
1763 width = CORE_ATTR(width);
1764 height = inc;
1765 }
1766 /* large increment, use default area */
1767 }
1768 }
1769 /* horizontal scrolling */
1770 else if(w == HTML_ATTR(hsb))
1771 {
1772 /*
1773 * clicking on the slider causes activation of the scrollbar
1774 * callbacks. Since there is no real movement, just return.
1775 * Not doing this will cause an entire redraw of the window.
1776 */
1777 if(value == HTML_ATTR(scroll_x))
1778 return; /* fix 01/20/97-01 kdh */
1779
1780 /* moving right (text moving left) */
1781 if (value > HTML_ATTR(scroll_x))
1782 {
1783 inc = value - HTML_ATTR(scroll_x);
1784
1785 /* save new value */
1786 HTML_ATTR(scroll_x) = value;
1787
1788 /* small increment */
1789 if(inc < HTML_ATTR(work_width))
1790 {
1791 /*
1792 * See if we have a vsb. If we have, no additional offset
1793 * required, otherwise we also have to clear the space that
1794 * has been reserved for it.
1795 */
1796 if(!HTML_ATTR(needs_vsb))
1797 #ifdef NO_XLIB_ILLEGAL_ACCESS
1798 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1799 #else
1800 vsb_width = ATTR_CORE(HTML_ATTR(vsb), width);
1801 #endif
1802 /****
1803 * Set clipmask for proper form scrolling only if we're
1804 * in range
1805 *****/
1806 if(form && form->can_clip)
1807 {
1808 int xs = form->x - value;
1809 int ys = form->y - HTML_ATTR(scroll_y);
1810
1811 if(xs + form->width < 0 || xs > HTML_ATTR(work_width) ||
1812 ys + form->height < 0 || ys > HTML_ATTR(work_height))
1813 ;
1814 else
1815 {
1816 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), form->clip);
1817 tka->SetClipOrigin(tka->dpy, HTML_ATTR(gc), xs, ys);
1818 }
1819 }
1820
1821 /* copy area to the left */
1822 tka->CopyArea(tka->dpy, tka->win, tka->win, HTML_ATTR(gc),
1823 inc, 0, HTML_ATTR(work_width) - inc,
1824 HTML_ATTR(work_height), 0, 0);
1825
1826 if(form)
1827 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), None);
1828
1829 /* clear area on right */
1830 x = HTML_ATTR(work_width) - inc;
1831 y = 0;
1832 width = inc + HTML_ATTR(margin_width) + vsb_width;
1833 height = HTML_ATTR(work_height);
1834 }
1835 /* large increment, use default area */
1836 }
1837 /* moving left (text moving right) */
1838 else
1839 {
1840 inc = HTML_ATTR(scroll_x) - value;
1841
1842 /* save new value */
1843 HTML_ATTR(scroll_x) = value;
1844
1845 /* small increment */
1846 if(inc < HTML_ATTR(work_width))
1847 {
1848 if(!HTML_ATTR(needs_vsb))
1849 #ifdef NO_XLIB_ILLEGAL_ACCESS
1850 _XmHTMLGetScrollDim(html, &hsb_height, &vsb_width);
1851 #else
1852 vsb_width = ATTR_CORE(HTML_ATTR(vsb), width);
1853 #endif
1854 /****
1855 * Set clipmask for proper form scrolling only if we're
1856 * in range
1857 *****/
1858 if(form && form->can_clip)
1859 {
1860 int xs = form->x - value;
1861 int ys = form->y - HTML_ATTR(scroll_y);
1862
1863 if(xs + form->width < 0 || xs > HTML_ATTR(work_width) ||
1864 ys + form->height < 0 || ys > HTML_ATTR(work_height))
1865 ;
1866 else
1867 {
1868 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), form->clip);
1869 tka->SetClipOrigin(tka->dpy, HTML_ATTR(gc), xs, ys);
1870 }
1871 }
1872
1873 /* copy area to the right */
1874 /* fix 01/24/97-01, kdh */
1875 tka->CopyArea(tka->dpy, tka->win, tka->win, HTML_ATTR(gc), 0, 0,
1876 HTML_ATTR(work_width) - inc + HTML_ATTR(margin_width) +
1877 vsb_width,
1878 HTML_ATTR(work_height), inc, 0);
1879
1880 if(form)
1881 tka->SetClipMask(tka->dpy, HTML_ATTR(gc), None);
1882
1883 /* clear area on left */
1884 x = y = 0;
1885 width = inc;
1886 height = HTML_ATTR(work_height);
1887 }
1888 /* large increment, use default area */
1889 }
1890 }
1891 else
1892 {
1893 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLMoveToPos"), XMHTML_MSG_10);
1894 return;
1895 }
1896
1897 /* update display */
1898 if (0) { /* Not radical enough it seems.
1899 Causes refresh problems when scroll bar is moved
1900 ZSS: March 2012 */
1901 _XmHTMLClearArea(html, x, y, width, height);
1902 } else { /* overkill, but seems to get rid of refresh problem.
1903 It does add some unpleasant flicker though ...*/
1904 XmHTMLRefresh((Widget)html);
1905 }
1906 }
1907