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