1 #ifndef production
2 static char rcsId[]="$Header$";
3 #endif
4 /*****
5 * frames.c : XmHTML frame support
6 *
7 * This file Version	$Revision$
8 *
9 * Creation date:		Tue Mar 25 18:53:12 GMT+0100 1997
10 * Last modification: 	$Date$
11 * By:					$Author$
12 * Current State:		$State$
13 *
14 * Author:				newt
15 *
16 * Copyright (C) 1994-1997 by Ripley Software Development
17 * All Rights Reserved
18 *
19 * This file is part of the XmHTML Widget Library.
20 *
21 * This library is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU Library General Public
23 * License as published by the Free Software Foundation; either
24 * version 2 of the License, or (at your option) any later version.
25 *
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29 * Library General Public License for more details.
30 *
31 * You should have received a copy of the GNU Library General Public
32 * License along with this library; if not, write to the Free
33 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 *
35 * Note:
36 * Many thanks to Eric Bello <belloer@gemse.fr> for fixing the original
37 * code!!
38 *****/
39 /*****
40 * ChangeLog
41 * $Log$
42 * Revision 1.1  2011/06/30 16:10:30  rwcox
43 * Cadd
44 *
45 * Revision 1.10  1998/04/27 06:59:39  newt
46 * tka stuff and a few bugfixes in argument checking
47 *
48 * Revision 1.9  1998/04/04 06:28:10  newt
49 * XmHTML Beta 1.1.3
50 *
51 * Revision 1.8  1997/10/23 00:25:01  newt
52 * XmHTML Beta 1.1.0 release
53 *
54 * Revision 1.7  1997/08/31 17:35:37  newt
55 * Several fixes in form creation & destruction and widget reuse. kd & rr
56 *
57 * Revision 1.6  1997/08/30 01:04:16  newt
58 * _XmHTMLWarning proto & color changes: XmHTML now uses manager's color fields.
59 *
60 * Revision 1.5  1997/08/01 13:01:40  newt
61 * my_strdup -> strdup, minor bugfixes and updated comments.
62 *
63 * Revision 1.4  1997/05/28 01:48:13  newt
64 * Sped up _XmHTMLCheckForFrames considerably.
65 *
66 * Revision 1.3  1997/04/29 14:27:00  newt
67 * Header files modifications.
68 *
69 * Revision 1.2  1997/04/03 05:35:36  newt
70 * Changed default name from _top to _frame appended with a number
71 *
72 * Revision 1.1  1997/03/28 07:02:46  newt
73 * Initial Revision
74 *
75 *****/
76 #ifdef HAVE_CONFIG_H
77 #include <config.h>
78 #endif
79 
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <string.h>
83 
84 #include "toolkit.h"
85 #include XmHTMLPrivateHeader
86 #include "stack.h"
87 
88 /*** External Function Prototype Declarations ***/
89 
90 /*** Public Variable Declarations ***/
91 /* how many times may we retry frame alignment? */
92 #define MAX_FRAME_ITERATIONS	100
93 #define ROW	1
94 #define COL	2
95 #define ROW_COL	4
96 
97 /* usefull defines */
98 #define IS_FRAMESET(F) \
99 		((F)->is_frameset)
100 #define IS_FRAME_SIZE_RELATIVE(F) \
101 		((F)->size_type == FRAME_SIZE_RELATIVE)
102 #define IS_FRAME_SIZE_OPTIONAL(F) \
103 		((F)->size_type == FRAME_SIZE_OPTIONAL)
104 #define IS_FRAME_SIZE_FIXED(F) \
105 		((F)->size_type == FRAME_SIZE_FIXED)
106 #define IS_FRAMESET_LAYOUT_ROWS(F) \
107 		(IS_FRAMESET(F) && ((F)->layout == FRAMESET_LAYOUT_ROWS))
108 #define IS_FRAMESET_LAYOUT_COLS(F) \
109 		(IS_FRAMESET(F) && ((F)->layout == FRAMESET_LAYOUT_COLS))
110 #define IS_FRAMESET_LAYOUT_ROW_COLS(F) \
111 		(IS_FRAMESET(F) && ((F)->layout == FRAMESET_LAYOUT_ROW_COLS))
112 
113 
114 /*** Private Datatype Declarations ****/
115 
116 /* definition of a HTML frameset */
117 typedef struct _frameSet{
118 	int type;					/* type of this set, either ROW or COL */
119 	int border;					/* frame border value */
120 	int *sizes;					/* array of child sizes */
121 	FrameSize *size_types;		/* array of possible size specifications */
122 	int nchilds;				/* max no of childs */
123 	int childs_done;			/* no of childs processed so far */
124 	int insert_pos;				/* insertion position of current child */
125 	struct _frameSet *parent;	/* parent frameset of this frameset */
126 	struct _frameSet *childs;	/* list of childs */
127 	struct _frameSet *next;		/* ptr to next frameSet */
128 	XmHTMLFrameWidget *actualFrameSet; /* ptr to saved FrameSet */
129 }frameSet;
130 
131 /* stack of framesets */
132 typedef struct _frameStack{
133 	frameSet  *frame_set;
134 	struct _frameStack *next;
135 }frameStack;
136 
137 /*** Private Function Prototype Declarations ****/
138 static frameSet *popFrameSet(void);
139 static void	pushFrameSet(frameSet *frame_set);
140 static frameSet	*doFrameSet(String attributes);
141 static XmHTMLFrameWidget *doFrame(XmHTMLWidget html, String attributes);
142 static void	insertFrameSetChild(frameSet *parent, frameSet *child);
143 static void	insertFrameChild(frameSet *current_set, XmHTMLFrameWidget *frame);
144 static void	makeFrameSets(XmHTMLWidget html, XmHTMLObject *frameset);
145 static void	adjustConstraints(XmHTMLWidget html);
146 static void	adjustFrame(XmHTMLFrameWidget *parent, int *p_width, int *p_height);
147 static void	destroyFrameSets(frameSet *set);
148 static void	mapFrames(XmHTMLWidget html);
149 static void frameDestroyCallback(XmHTMLWidget html, XmHTMLFrameWidget *frame);
150 
151 /*** Private Variable Declarations ***/
152 static int current_frame;		/* running frame counter */
153 static frameSet *frame_sets;	/* list of all framesets processed */
154 static frameStack frame_base, *frame_stack;
155 
156 /*****
157 * Name: 		pushFrameSet
158 * Return Type: 	void
159 * Description: 	pushes a frameset on the stack
160 * In:
161 *	frame_set:	frameset to push
162 * Returns:
163 *	nothing
164 *****/
165 static void
pushFrameSet(frameSet * frame_set)166 pushFrameSet(frameSet *frame_set)
167 {
168 	frameStack *tmp;
169 
170 	tmp = (frameStack*)malloc(sizeof(frameStack));
171 	tmp->frame_set = frame_set;
172 	tmp->next = frame_stack;
173 	frame_stack = tmp;
174 }
175 
176 /*****
177 * Name: 		popFrameSet
178 * Return Type: 	frameSet*
179 * Description: 	pops a frameset of the stack
180 * In:
181 *	nothing
182 * Returns:
183 *	the next frameset on the stack, or NULL when stack is empty
184 *****/
185 static frameSet*
popFrameSet(void)186 popFrameSet(void)
187 {
188 	frameStack *tmp;
189 	frameSet *frame_set;
190 
191 	if(frame_stack->next)
192 	{
193 		tmp = frame_stack;
194 		frame_stack = frame_stack->next;
195 		frame_set = tmp->frame_set;
196 		free(tmp);
197 		return(frame_set);
198 	}
199 	return(NULL);
200 }
201 
202 /*****
203 * Name: 		doFrameSet
204 * Return Type: 	frameSet*
205 * Description: 	creates and fills a frameSet structure with the info in it's
206 *				attributes
207 * In:
208 *	attributes:	attributes for this frameset
209 * Returns:
210 *	a newly created frameset.
211 * Note:
212 *	this routine inserts each frameset it creates in a linked list which
213 *	is used for stack purposes.
214 *****/
215 static frameSet*
doFrameSet(String attributes)216 doFrameSet(String attributes)
217 {
218 	frameSet *list, *tmp;
219 	String chPtr, tmpPtr, ptr;
220 	int i;
221 
222 	/* nothing to do if no attributes */
223 	if(attributes == NULL)
224 		return(frame_sets);
225 
226 	/* create new entry */
227 	list = (frameSet*)malloc(sizeof(frameSet));
228 	(void)memset(list, 0, sizeof(frameSet));
229 
230 	list->type = ROW;
231 
232 	if((chPtr = _XmHTMLTagGetValue(attributes, "rows")) == NULL)
233 	{
234 		if((chPtr = _XmHTMLTagGetValue(attributes, "cols")) == NULL)
235 		{
236 			/* useless sanity, should be catched upon entry */
237 			free(list);
238 			return(frame_sets);
239 		}
240 		else
241 			list->type = COL;
242 	}
243 
244 	/*
245 	* count how many childs this frameset has: the no of childs is given by
246 	* the no of entries within the COLS or ROWS tag
247 	* Note that childs can be frames and/or framesets as well.
248 	*/
249 	for(tmpPtr = chPtr; *tmpPtr != '\0'; tmpPtr++)
250 		if(*tmpPtr == ',')
251 			list->nchilds++;
252 	list->nchilds++;
253 
254 	list->sizes = (int*)calloc(list->nchilds, sizeof(int));
255 	list->size_types = (FrameSize*)calloc(list->nchilds, sizeof(FrameSize));
256 	list->childs = (frameSet*)calloc(list->nchilds, sizeof(frameSet));
257 
258 	/*****
259 	* get dimensions: when we encounter a ``*'' in a size definition it
260 	* means we are free to choose any size we want. When its a number
261 	* followed by a ``%'' we must choose the size relative against the total
262 	* width of the render area. When it's a number not followed by anything
263 	* we have an absolute size.
264 	*****/
265 	tmpPtr = ptr = chPtr;
266 	i = 0;
267 	while(True)
268 	{
269 		if(*tmpPtr == ',' || *tmpPtr == '\0')
270 		{
271 			if(*(tmpPtr-1) == '*')
272 				list->size_types[i] = FRAME_SIZE_OPTIONAL;
273 			else if(*(tmpPtr-1) == '%')
274 				list->size_types[i] = FRAME_SIZE_RELATIVE;
275 			else
276 				list->size_types[i] = FRAME_SIZE_FIXED;
277 
278 			list->sizes[i++] = atoi(ptr);
279 
280 			if(*tmpPtr == '\0')
281 				break;
282 			ptr = tmpPtr+1;
283 		}
284 		tmpPtr++;
285 		/* sanity */
286 		if(i == list->nchilds)
287 			break;
288 	}
289 	free(chPtr);
290 
291 	/*****
292 	* Frame borders can be specified by both frameborder or border, they
293 	* are equal.
294 	*****/
295 	if((chPtr = _XmHTMLTagGetValue(attributes, "frameborder")) != NULL)
296 	{
297 		/*
298 		* Sigh, stupid Netscape frameset definition allows a tag to have
299 		* a textvalue or a number.
300 		*/
301 		if(!(strcasecmp(chPtr, "no")) || *chPtr == '0')
302 			list->border = 0;
303 		else
304 			list->border = atoi(chPtr);
305 		free(chPtr);
306 	}
307 	else
308 		list->border = _XmHTMLTagGetNumber(attributes, "border", 5);
309 
310 	/* insert this new frame in the overal frameset list. */
311 	if(frame_sets == NULL)
312 		frame_sets = list;
313 	else
314 	{
315 		for(tmp = frame_sets; tmp != NULL && tmp->next != NULL;
316 			tmp = tmp->next);
317 		tmp->next = list;
318 	}
319 
320 	/* create actual representation of frameset */
321 	{
322 	  XmHTMLFrameWidget *actualFrameSet = NULL ;
323 	  actualFrameSet = (XmHTMLFrameWidget*)calloc(1, sizeof(XmHTMLFrameWidget));
324 	  actualFrameSet->is_frameset = True ;
325 	  actualFrameSet->layout =
326 			(list->type == ROW ? FRAMESET_LAYOUT_ROWS : FRAMESET_LAYOUT_COLS);
327 	  list->actualFrameSet = actualFrameSet ;
328 	}
329 	return(list);
330 }
331 
332 /*****
333 * Name: 		doFrame
334 * Return Type: 	XmHTMLFrameWidget*
335 * Description: 	fills a HTML frame structure with data from it's attributes
336 * In:
337 *	html:		XmHTMLWidget id;
338 *	attributes:	frame attributes
339 * Returns:
340 *	updated frame
341 * Note:
342 *	this routine takes the frame to update from an already allocated list
343 *	of frames and increments the running frame counter when it returns.
344 *****/
345 static XmHTMLFrameWidget*
doFrame(XmHTMLWidget html,String attributes)346 doFrame(XmHTMLWidget html, String attributes)
347 {
348 	XmHTMLFrameWidget *frame;
349 	String chPtr;
350 
351 	frame = html->html.frames[current_frame];
352 
353 	/* default frame sizing & scrolling */
354 	frame->size_type = FRAME_SIZE_FIXED;
355 	frame->scroll_type = FRAME_SCROLL_AUTO;
356 
357 	/* get frame name, default to _frame if not present */
358 	if(!attributes ||
359 		(frame->name = _XmHTMLTagGetValue(attributes, "name")) == NULL)
360 	{
361 		char buf[24];
362 		sprintf(buf, "_frame%i", current_frame);
363 		frame->name = strdup(buf);
364 	}
365 
366 	/* pick up all remaining frame attributes */
367 	if(attributes)
368 	{
369 		frame->src = _XmHTMLTagGetValue(attributes, "src");
370 		frame->margin_width = (Dimension)_XmHTMLTagGetNumber(attributes,
371 			"marginwidth", 5);
372 		frame->margin_height = (Dimension)_XmHTMLTagGetNumber(attributes,
373 			"marginheight", 5);
374 
375 		/* inherit margins from parent if we'd gotten an invalid spec */
376 		if(!frame->margin_width)
377 			frame->margin_width = html->html.margin_width;
378 		if(!frame->margin_height)
379 			frame->margin_height = html->html.margin_height;
380 
381 		/*
382 		* This is useless as we don't support frame resizing. I think this is
383 		* a thing the caller must be able to do. A possible way could be to
384 		* overlay the render area with a PanedWidget and store these HTML
385 		* widgets as childs of this paned widget.
386 		*/
387 		frame->resize = !_XmHTMLTagCheck(attributes, "noresize");
388 
389 		/* what about scrolling? */
390 		if((chPtr = _XmHTMLTagGetValue(attributes, "scrolling")) != NULL)
391 		{
392 			if(!(strcasecmp(chPtr, "yes")))
393 				frame->scroll_type = FRAME_SCROLL_YES;
394 			else if(!(strcasecmp(chPtr, "no")))
395 				frame->scroll_type = FRAME_SCROLL_NONE;
396 			free(chPtr);
397 		}
398 	}
399 	else
400 	{
401 		frame->src           = NULL;
402 		frame->margin_width  = 5;
403 		frame->margin_height = 5;
404 		frame->resize        = True;
405 	}
406 
407 	_XmHTMLDebug(11, ("frames.c: doFrame, frame %i created\n"
408 		"\tname: %s\n"
409 		"\tsrc : %s\n"
410 		"\tmargin width : %i\n"
411 		"\tmargin height: %i\n"
412 		"\tresize       : %s\n"
413 		"\tscrolling    : %s\n", current_frame, frame->name,
414 		frame->src ? frame->src : "<none>", frame->margin_width,
415 		frame->margin_height, frame->resize ? "yes" : "no",
416 		frame->scroll_type == FRAME_SCROLL_AUTO ? "auto" :
417 		(frame->scroll_type == FRAME_SCROLL_YES ? "always" : "none")));
418 
419 	/*
420 	* Actual widget creation is postponed until the very last moment
421 	* of _XmHTMLCreateFrames
422 	*/
423 
424 	/* increment running frame counter */
425 	current_frame++;
426 	return(frame);
427 }
428 
429 /*****
430 * Name: 		insertFrameSetChild
431 * Return Type: 	void
432 * Description: 	inserts a child frameset in it's parent list
433 * In:
434 *	parent:		parent of this frameset
435 *	child:		obvious
436 * Returns:
437 *	nothing
438 *****/
439 static void
insertFrameSetChild(frameSet * parent,frameSet * child)440 insertFrameSetChild(frameSet *parent, frameSet *child)
441 {
442 	if(parent && parent->childs_done < parent->nchilds)
443 	{
444 		int idx = parent->childs_done;
445 		XmHTMLFrameWidget *c, *dad, *son;
446 
447 		child->parent = parent;
448 		child->insert_pos = idx;
449 
450 		dad = parent->actualFrameSet;
451 		son = child->actualFrameSet;
452 
453 		son->size_s = parent->sizes[child->insert_pos];
454 		son->size_type = parent->size_types[child->insert_pos];
455 
456 		if(son->size_s == 0)
457 			son->size_type = FRAME_SIZE_OPTIONAL;
458 
459 		/* set additional constraints for this frame */
460 		son->border = parent->border;
461 
462 		/* disable resizing if we don't have a border */
463 		if(!son->border)
464 			son->resize = False;
465 
466 		for(c = dad->children ; c != NULL ; c = c->next)
467 			if(!c->next)
468 				break;
469 		if(c)
470 			c->next = son;
471 		else
472 			dad->children = son ;
473 		son->prev = c ;
474 		son->frameset = dad ;
475 
476 		parent->childs[parent->childs_done] = *child;
477 		parent->childs_done++;
478 	}
479 }
480 
481 /*****
482 * Name: 		insertFrameChild
483 * Return Type: 	void
484 * Description: 	sets the geometry constraints on a HTML frame
485 * In:
486 *	frame_set:	frameset parent of this frame;
487 *	frame:		frame for which to set the constraints
488 * Returns:
489 *	nothing, but frame is updated.
490 *****/
491 static void
insertFrameChild(frameSet * frame_set,XmHTMLFrameWidget * frame)492 insertFrameChild(frameSet *frame_set, XmHTMLFrameWidget *frame)
493 {
494 	XmHTMLFrameWidget *c, *dad;
495 	int insert_pos = frame_set->childs_done;
496 
497 	frame->size_s = frame_set->sizes[insert_pos];
498 	frame->size_type = frame_set->size_types[insert_pos];
499 
500 	if(frame->size_s == 0)
501 		frame->size_type = FRAME_SIZE_OPTIONAL;
502 
503 	/* set additional constraints for this frame */
504 	frame->border = frame_set->border;
505 
506 	/* disable resizing if we don't have a border */
507 	if(!frame->border)
508 	  frame->resize = False;
509 
510 	dad = frame_set->actualFrameSet;
511 	for(c = dad->children ; c != NULL ; c = c->next)
512 		if(!c->next)
513 			break;
514 	if(c)
515 		c->next = frame;
516 	else
517 		dad->children = frame;
518 	frame->prev = c;
519 	frame->frameset = dad;
520 
521 	frame_set->childs_done++;
522 }
523 
524 /*****
525 * Name: 		makeFrameSets
526 * Return Type: 	void
527 * Description: 	creates all HTML framesets and sets the geometry constraints
528 *				on each frame.
529 * In:
530 *	html:		XmHTMLWidget id;
531 *	frameset:	XmHTMLObject data;
532 * Returns:
533 *	nothing
534 * Note:
535 *	This routine was *very* difficult to conceive, so don't let the simplicity
536 *	of it deceive you.
537 *****/
538 static void
makeFrameSets(XmHTMLWidget html,XmHTMLObject * frameset)539 makeFrameSets(XmHTMLWidget html, XmHTMLObject *frameset)
540 {
541 	XmHTMLObject *tmp;
542 	XmHTMLFrameWidget *frame;
543 	frameSet *current_set = NULL, *parent_set = NULL;
544 	int idx = 0;
545 
546 	for(tmp = frameset; tmp != NULL; tmp = tmp->next)
547 	{
548 		switch(tmp->id)
549 		{
550 			case HT_FRAMESET:
551 				if(tmp->is_end)
552 				{
553 					/* frameset terminated, pop from stack */
554 					current_set = popFrameSet();
555 					/*
556 					* no more sets left on the stack: we've reached the
557 					* end of the outermost frameset and are done here.
558 					*/
559 					if(current_set == NULL)
560 						return;
561 				}
562 				else
563 				{
564 					/* A new frameset, push the current frameset on the stack */
565 					pushFrameSet(current_set);
566 					parent_set = frame_stack->frame_set;
567 
568 					/* Check if we still have room for this thing. */
569 					if(!parent_set ||
570 						parent_set->childs_done < parent_set->nchilds)
571 					{
572 						/* create a new frameset */
573 						current_set = doFrameSet(tmp->attributes);
574 						insertFrameSetChild(parent_set, current_set);
575 						idx = 0;
576 					}
577 					else
578 					{
579 						/*
580 						* No more room available, this is an unspecified
581 						* frameset, kill it and all childs it might have.
582 						*/
583 						int depth = 1;
584 						int start_line = tmp->line;
585 						for(tmp = tmp->next; tmp != NULL; tmp = tmp->next)
586 						{
587 							if(tmp->id == HT_FRAMESET)
588 							{
589 								if(tmp->is_end)
590 								{
591 									if(--depth == 0)
592 										break;
593 								}
594 								else	/* child frameset */
595 									depth++;
596 							}
597 						}
598 						_XmHTMLWarning(__WFUNC__(html, "doFrameSets"),
599 							XMHTML_MSG_58, start_line, tmp ? tmp->line : -1);
600 					}
601 				}
602 				break;
603 			case HT_FRAME:
604 				/* check if we have room left */
605 				if(current_set->childs_done < current_set->nchilds)
606 				{
607 					/* insert child in current frameset */
608 					frame = doFrame(html, tmp->attributes);
609 					insertFrameChild(current_set, frame);
610 					idx++;
611 				}
612 				else
613 					_XmHTMLWarning(__WFUNC__(html, "doFrameSets"),
614 						XMHTML_MSG_59, tmp->line);
615 				/*****
616 				* Note: </FRAME> doesn't exist. The parser is smart enough
617 				* to kick these out.
618 				*****/
619 				/* fall thru */
620 			default:
621 				break;
622 		}
623 		if(idx == html->html.nframes)
624 			return;
625 	}
626 }
627 
628 static XmHTMLFrameWidget*
getRootFrameset(XmHTMLWidget html)629 getRootFrameset(XmHTMLWidget html)
630 {
631 	XmHTMLFrameWidget *frame;
632 
633 	for (frame = html->html.frames[0];
634 		frame != NULL && frame->frameset != NULL; frame = frame->frameset);
635 
636 	return(frame);
637 }
638 
639 
640 static void
adjustFramesetRows(XmHTMLFrameWidget * parent,int * p_width,int * p_height)641 adjustFramesetRows(XmHTMLFrameWidget *parent, int *p_width, int *p_height)
642 {
643 	XmHTMLFrameWidget *child = NULL ;
644 	int width, height ;
645 	int cum_fixed_size = 0, cum_rel_size = 0, cum_opt_size = 0 ;
646 
647 	/* Begin with fixed-sized children */
648 	cum_fixed_size = 0 ;
649 	for (child = parent->children ; child != NULL ; child = child->next)
650 	{
651 		if(IS_FRAME_SIZE_FIXED(child))
652 		{
653 			width = *p_width ;
654 			height = child->size_s ;
655 
656 			adjustFrame(child, &width, &height);
657 
658 			child->width = width ;
659 			child->height = height ;
660 			cum_fixed_size += height ;
661 		}
662 	}
663 
664 	/* Then do relative-sized children */
665 	cum_rel_size = 0 ;
666 	for (child = parent->children ; child != NULL ; child = child->next)
667 	{
668 		if(IS_FRAME_SIZE_RELATIVE(child))
669 		{
670 			width = *p_width ;
671 			height = child->size_s * (*p_height) / 100 ;
672 
673 			adjustFrame(child, &width, &height);
674 
675 			child->width = width ;
676 			child->height = height ;
677 			cum_rel_size += height ;
678 		}
679 	}
680 
681 	/* Finally, end up with optional-sized children */
682 	cum_opt_size = 0 ;
683 	{
684 		int nb_opt = 0;
685 
686 		/* count how many optional they are */
687 		for (child = parent->children ; child != NULL ; child = child->next)
688 			if(IS_FRAME_SIZE_OPTIONAL(child))
689 				++nb_opt;
690 
691 		if(nb_opt > 0)
692 		{
693 			int cum_size, remain_size, mean_opt_size ;
694 
695 			/*****
696 			* stupid hack : equal sizes for all optional fields.
697 			* FIXME! find sth smarter than that!
698 			*****/
699 			cum_size = cum_fixed_size + cum_rel_size ;
700 			remain_size = *p_height - cum_size ;
701 			if(remain_size <= nb_opt)
702 				remain_size = nb_opt ;
703 			mean_opt_size = remain_size / nb_opt ;
704 
705 			/* go adjust */
706 			for(child = parent->children ; child != NULL ; child = child->next)
707 			{
708 				if(IS_FRAME_SIZE_OPTIONAL(child))
709 				{
710 					width = *p_width ;
711 					height = mean_opt_size ;
712 
713 					adjustFrame(child, &width, &height);
714 
715 					child->width = width ;
716 					child->height = height ;
717 					cum_opt_size += height ;
718 				}
719 			}
720 		}
721 	} /* end of optional-sized children mgt */
722 
723 #ifdef FEEDBACK_SIZES
724 	*p_height = cum_fixed_size + cum_rel_size + cum_opt_size ;
725 	if(*p_height <= 0)
726 		*p_height = 1 ;
727 #endif
728 }
729 
730 static void
adjustFramesetColumns(XmHTMLFrameWidget * parent,int * p_width,int * p_height)731 adjustFramesetColumns(XmHTMLFrameWidget *parent, int *p_width, int *p_height)
732 {
733 	XmHTMLFrameWidget *child = NULL ;
734 	int width, height ;
735 	int cum_fixed_size = 0, cum_rel_size = 0, cum_opt_size = 0 ;
736 
737 	/* Begin with fixed-sized children */
738 	cum_fixed_size = 0 ;
739 	for(child = parent->children ; child != NULL ; child = child->next)
740 	{
741 		if(IS_FRAME_SIZE_FIXED(child))
742 		{
743 			width = child->size_s ;
744 			height = *p_height ;
745 
746 			adjustFrame(child, &width, &height);
747 
748 			child->width = width ;
749 			child->height = height ;
750 			cum_fixed_size += width ;
751 		}
752 	}
753 
754 	/* Then do relative-sized children */
755 	cum_rel_size = 0 ;
756 	for (child = parent->children ; child != NULL ; child = child->next)
757     {
758 		if(IS_FRAME_SIZE_RELATIVE(child))
759 		{
760 			width = child->size_s * (*p_width) / 100 ;
761 			height = *p_height ;
762 
763 			adjustFrame(child, &width, &height);
764 
765 			child->width = width ;
766 			child->height = height ;
767 			cum_rel_size += width ;
768 		}
769 	}
770 
771 	/* Finally, end up with optional-sized children */
772 	cum_opt_size = 0 ;
773 	{
774 		int nb_opt = 0;
775 
776 		/* count how many optional they are */
777 		for (child = parent->children ; child != NULL ; child = child->next)
778 			if(IS_FRAME_SIZE_OPTIONAL(child))
779 				++nb_opt;
780 
781 		if(nb_opt > 0)
782 		{
783 			int cum_size, remain_size, mean_opt_size ;
784 
785 			/*****
786 			* stupid hack : equal sizes for all optional fields.
787 			* FIXME! find sth smarter than that!
788 			*****/
789 			cum_size = cum_fixed_size + cum_rel_size ;
790 			remain_size = *p_width - cum_size ;
791 			if(remain_size <= nb_opt)
792 				remain_size = nb_opt ;
793 			mean_opt_size = remain_size / nb_opt ;
794 
795 			/* go adjust */
796 			for(child = parent->children ; child != NULL ; child = child->next)
797 			{
798 				if(IS_FRAME_SIZE_OPTIONAL(child))
799 				{
800 					width = mean_opt_size ;
801 					height = *p_height ;
802 
803 					adjustFrame(child, &width, &height);
804 
805 					child->width = width ;
806 					child->height = height ;
807 					cum_opt_size += width ;
808 				}
809 			}
810 		}
811 	} /* end of optional-sized children mgt */
812 
813 #ifdef FEEDBACK_SIZES
814 	*p_width = cum_fixed_size + cum_rel_size + cum_opt_size ;
815 	if(*p_width <= 0)
816 		*p_width = 1 ;
817 #endif
818 }
819 
820 static void
adjustFrame(XmHTMLFrameWidget * parent,int * p_width,int * p_height)821 adjustFrame(XmHTMLFrameWidget *parent, int *p_width, int *p_height)
822 {
823 	if(*p_width <= 0)
824 		*p_width = 1 ;
825 	if(*p_height <= 0)
826 		*p_height = 1 ;
827 
828 	if(IS_FRAMESET(parent)) /* do recursion only if it is a frameset */
829 	{
830 		if(parent->layout == FRAMESET_LAYOUT_ROWS)
831 			adjustFramesetRows(parent, p_width, p_height);
832 		else if(parent->layout == FRAMESET_LAYOUT_COLS)
833 			adjustFramesetColumns(parent, p_width, p_height);
834 	}
835 }
836 
837 static void
locateFrame(XmHTMLFrameWidget * parent,int x,int y)838 locateFrame(XmHTMLFrameWidget *parent, int x, int y)
839 {
840 	parent->x = x;
841 	parent->y = y;
842 
843 	if(IS_FRAMESET(parent)) /* do recursion only if it is a frameset */
844 	{
845 		XmHTMLFrameWidget *frame ;
846 
847 		if(IS_FRAMESET_LAYOUT_ROWS(parent))
848 		{
849 			for(frame = parent->children ; frame != NULL ; frame = frame->next)
850 			{
851 				locateFrame(frame, x, y);
852 				y += frame->height ;
853 			}
854 		}
855 
856 		if(IS_FRAMESET_LAYOUT_COLS(parent))
857 		{
858 			for(frame = parent->children ; frame != NULL ; frame = frame->next)
859 			{
860 				locateFrame(frame, x, y);
861 				x += frame->width ;
862 			}
863 		}
864 	}
865 }
866 
867 
868 static void
adjustConstraints(XmHTMLWidget html)869 adjustConstraints(XmHTMLWidget html)
870 {
871 	XmHTMLFrameWidget *root_frame;
872 	int work_width, work_height;
873 
874 	/* this uses the core dimensions */
875 	work_width = html->core.width;
876 	work_height = html->core.height;
877 
878 	/* get the root frame */
879 	root_frame = getRootFrameset(html);
880 
881 	/* adjust frames' dimensions */
882 	adjustFrame(root_frame, &work_width, &work_height);
883 
884 	/* adjust frames' positions */
885 	locateFrame(root_frame, 0, 0);
886 }
887 
888 
889 /*****
890 * Name: 		destroyFrameSets
891 * Return Type: 	void
892 * Description: 	destroys the memory used by the framesets
893 * In:
894 *	set:		list of framesets to be destroyed
895 * Returns:
896 *	nothing
897 *****/
898 static void
destroyFrameSets(frameSet * set)899 destroyFrameSets(frameSet *set)
900 {
901 	frameSet *tmp;
902 
903 	while(set)
904 	{
905 		tmp = set->next;
906 		if(set->sizes)
907 			free(set->sizes);
908 		if(set->size_types)
909 			free(set->size_types);
910 		if(set->childs)
911 			free(set->childs);
912 		free(set);
913 		set = tmp;
914 	}
915 	set = NULL;
916 }
917 
918 /*****
919 * Name: 		mapFrames
920 * Return Type: 	void
921 * Description: 	map's all XmHTML frame childs to screen
922 * In:
923 *	html:		XmHTMLWidget id
924 * Returns:
925 *	nothing
926 *****/
927 static void
mapFrames(XmHTMLWidget html)928 mapFrames(XmHTMLWidget html)
929 {
930 	XmHTMLFrameWidget *frame;
931 	int i;
932 
933 	/* map all XmHTML frame childs */
934 	for(i = 0; i < html->html.nframes; i++)
935 	{
936 		frame = html->html.frames[i];
937 		/* map to screen */
938 		HTML_ATTR(tka)->SetMappedWhenManaged(frame->frame, True);
939 		/* call notifier */
940 		_XmHTMLFrameDoneCallback(html, frame, frame->frame);
941 	}
942 	/* resync */
943 	if(HTML_ATTR(gc))
944 		HTML_ATTR(tka)->Sync(HTML_ATTR(tka)->dpy, False);
945 }
946 
947 /*****
948 * Name: 		frameDestroyCallback
949 * Return Type: 	void
950 * Description: 	frame destruction notifier
951 * In:
952 *	html:		XmHTMLWidget id;
953 *	frame:		frame data;
954 * Returns:
955 *	nothing
956 *****/
957 static void
frameDestroyCallback(XmHTMLWidget html,XmHTMLFrameWidget * frame)958 frameDestroyCallback(XmHTMLWidget html, XmHTMLFrameWidget *frame)
959 {
960 	int ret_val;
961 
962 	if((ret_val = _XmHTMLFrameDestroyCallback(html, frame)) == -1)
963 		return;
964 
965 	/* always destroy this */
966 	if(frame->src) {
967 	  free(frame->src);
968 	  frame->src = NULL; /* sanity */
969 	}
970 	if(frame->name) {
971 	  free(frame->name);
972 	  frame->name = NULL; /* sanity */
973 	}
974 	frame->frameset = NULL; /* sanity */
975 
976 	/* return if we may not destroy this frame */
977 	if(ret_val == 0)
978 	{
979 		/* destroy frame data, but keep the widget alive */
980 		free(frame);
981 		frame = NULL;
982 		return;
983 	}
984 
985 	/* destroy everything */
986 	if(frame->frame)
987 		HTML_ATTR(tka)->DestroyWidget(frame->frame);
988 	free(frame);
989 	frame = NULL;
990 }
991 
992 static void
recursiveDestroyFrameset(XmHTMLFrameWidget * frame)993 recursiveDestroyFrameset(XmHTMLFrameWidget *frame)
994 {
995 	if (!frame) /* sanity */
996     return ;
997 
998 	if (IS_FRAMESET(frame))
999 	{
1000 		XmHTMLFrameWidget *child, *tmp ;
1001 		for(child = frame->children ; child != NULL ; )
1002 		{
1003 			tmp = child->next;
1004 			recursiveDestroyFrameset(child);
1005 			child = tmp ;
1006 		}
1007 		frame->children = NULL ;
1008 
1009 		if(frame->src)
1010 		{
1011 			free(frame->src);
1012 			frame->src = NULL; /* sanity */
1013 		}
1014 		if(frame->name)
1015 		{
1016 			free(frame->name);
1017 			frame->name = NULL; /* sanity */
1018 		}
1019 		frame->frameset = NULL; /* sanity */
1020 
1021 		free(frame);
1022 		frame = NULL ;
1023 	}
1024 }
1025 
1026 static Boolean
areAllSizesOptional(XmHTMLFrameWidget * frameset)1027 areAllSizesOptional(XmHTMLFrameWidget *frameset)
1028 {
1029 	Boolean all_opt = True ;
1030 	if (IS_FRAMESET(frameset))
1031 	{
1032    		XmHTMLFrameWidget *frame;
1033 
1034 		for(frame = frameset->children ; frame != NULL ; frame = frame->next)
1035 		{
1036 			if(IS_FRAME_SIZE_OPTIONAL(frame))
1037 			{
1038 				all_opt = False;
1039 				break;
1040 			}
1041 		}
1042 	}
1043 	return(all_opt);
1044 }
1045 
1046 static Boolean
areAllSizesRelative(XmHTMLFrameWidget * frameset)1047 areAllSizesRelative(XmHTMLFrameWidget *frameset)
1048 {
1049 	Boolean all_rel = False ;
1050 	if(IS_FRAMESET(frameset))
1051 	{
1052 		XmHTMLFrameWidget *frame;
1053 
1054 		all_rel = True ;
1055 		for(frame = frameset->children ; frame != NULL ; frame = frame->next)
1056 		{
1057 			if (IS_FRAME_SIZE_RELATIVE(frame))
1058 			{
1059 				all_rel = False;
1060 				break;
1061 			}
1062 		}
1063 	}
1064 	return(all_rel);
1065 }
1066 
1067 static int
relativeSizesSum(XmHTMLFrameWidget * frameset)1068 relativeSizesSum(XmHTMLFrameWidget *frameset)
1069 {
1070 	int rel_sum = 0 ;
1071 	if(IS_FRAMESET(frameset))
1072 	{
1073 		XmHTMLFrameWidget *frame;
1074 		for(frame = frameset->children ; frame != NULL ; frame = frame->next)
1075 		{
1076 			if (IS_FRAME_SIZE_RELATIVE(frame))
1077 			{
1078 				rel_sum += frame->size_s ;
1079 			}
1080 		}
1081 	}
1082 	return(rel_sum);
1083 }
1084 
1085 /********
1086 ****** Public Functions
1087 ********/
1088 
1089 /*****
1090 * Name: 		_XmHTMLCheckForFrames
1091 * Return Type: 	int
1092 * Description: 	checks if the given list of objects contains HTML frames
1093 * In:
1094 *	html:		XmHTMLWidget id;
1095 *	objects:	parser output to check
1096 * Returns:
1097 *	no of frames found in the current document.
1098 *****/
1099 int
_XmHTMLCheckForFrames(XmHTMLWidget html,XmHTMLObject * objects)1100 _XmHTMLCheckForFrames(XmHTMLWidget html, XmHTMLObject *objects)
1101 {
1102 	XmHTMLObject *tmp;
1103 	int nframes = 0;
1104 
1105 	/* we only support frames if user has attached a frame callback */
1106 	if(!html->html.frame_callback)
1107 		return(0);
1108 
1109 	/*
1110 	* frames are not allowed to appear inside the BODY tag.
1111 	* So we never have to walk the entire contents of the current document
1112 	* but simply break out of the loop once we encounter the <BODY> tag.
1113 	* This is a fairly huge performance increase.
1114 	*/
1115 	for(tmp = objects; tmp != NULL && tmp->id != HT_BODY; tmp = tmp->next)
1116 		if(tmp->id == HT_FRAME)
1117 			nframes++;
1118 
1119 	return(nframes);
1120 }
1121 
1122 /*****
1123 * Name: 		_XmHTMLDestroyFrames
1124 * Return Type: 	void
1125 * Description: 	frame destroyer
1126 * In:
1127 *	html:		XmHTMLWidget id
1128 *	nframes:	no of frames to destroy;
1129 * Returns:
1130 *	nothing, but the frames list of the widget is destroyed.
1131 *****/
1132 void
_XmHTMLDestroyFrames(XmHTMLWidget html,int nframes)1133 _XmHTMLDestroyFrames(XmHTMLWidget html, int nframes)
1134 {
1135 	int i = 0;
1136 	XmHTMLFrameWidget *root_frame = NULL;
1137 
1138 	/* unmap all XmHTML frame childs */
1139 	for(i = 0; i < html->html.nframes; i++)
1140 		HTML_ATTR(tka)->SetMappedWhenManaged(html->html.frames[i]->frame,False);
1141 
1142 	/* free them */
1143 	root_frame = getRootFrameset(html);
1144 	recursiveDestroyFrameset(root_frame);
1145 
1146 	for(i = 0; i < nframes; i++)
1147 	{
1148 		frameDestroyCallback(html, html->html.frames[i]);
1149 		html->html.frames[i] = NULL ;/* sanity */
1150 	}
1151 	free(html->html.frames);
1152 	html->html.frames = NULL;
1153 	html->html.nframes = 0;
1154 }
1155 
1156 /*****
1157 * Name: 		_XmHTMLReconfigureFrames
1158 * Return Type: 	void
1159 * Description: 	resize method for XmHTML frame childs
1160 * In:
1161 *	html:		XmHTMLWidget id
1162 * Returns:
1163 *	nothing
1164 *****/
1165 void
_XmHTMLReconfigureFrames(XmHTMLWidget html)1166 _XmHTMLReconfigureFrames(XmHTMLWidget html)
1167 {
1168 	XmHTMLFrameWidget *frame;
1169 	int i;
1170 
1171 	_XmHTMLDebug(11, ("frames.c: _XmHTMLReconfigureFrames Start\n"));
1172 	/* compute new screen positions */
1173 	adjustConstraints(html);
1174 
1175 	/* reconfigure all widgets */
1176 	for(i = 0; i < html->html.nframes; i++)
1177 	{
1178 		frame = html->html.frames[i];
1179 
1180 		_XmHTMLDebug(11, ("frames.c: _XmHTMLReconfigureFrames doing frame "
1181 			"%s.\n", frame->name));
1182 
1183 		HTML_ATTR(tka)->ConfigureWidget(frame->frame, frame->x, frame->y,
1184 			frame->width - frame->border,
1185 			frame->height - frame->border, frame->border);
1186 	}
1187 	_XmHTMLDebug(11, ("frames.c: _XmHTMLReconfigureFrames End.\n"));
1188 }
1189 
1190 /*****
1191 * Name:			_XmHTMLCreateFrame
1192 * Return Type: 	Widget
1193 * Description: 	creates a htmlWidgetClass widget for use in HTML frames.
1194 * In:
1195 *	html:		parent XmHTMLWidget id;
1196 *	frame:		data for frame (dimensions, name, ...)
1197 *	fptr:		callback data from the XmNframeCallback callback function.
1198 * Returns:
1199 *	A newly created XmHTMLWidget.
1200 *****/
1201 Widget
_XmHTMLCreateFrame(XmHTMLWidget html,XmHTMLFrameWidget * frame,XmHTMLFrameCallbackStruct * fptr)1202 _XmHTMLCreateFrame(XmHTMLWidget html, XmHTMLFrameWidget *frame,
1203 	XmHTMLFrameCallbackStruct *fptr)
1204 {
1205 	Arg args[20];
1206 	Dimension argc = 0;
1207 	static Widget widget;
1208 	XmHTMLWidget html_widget;
1209 	ToolkitAbstraction *tka = HTML_ATTR(tka);
1210 
1211 	/* set constraints and other frame stuff */
1212 	XtSetArg(args[argc], XmNx, frame->x); argc++;
1213 	XtSetArg(args[argc], XmNy, frame->y); argc++;
1214 	XtSetArg(args[argc], XmNwidth, frame->width - frame->border); argc++;
1215 	XtSetArg(args[argc], XmNheight, frame->height - frame->border); argc++;
1216 	XtSetArg(args[argc], XmNmarginWidth, frame->margin_width); argc++;
1217 	XtSetArg(args[argc], XmNmarginHeight, frame->margin_height); argc++;
1218 	XtSetArg(args[argc], XmNborderWidth, frame->border); argc++;
1219 	XtSetArg(args[argc], XmNborderColor, html->manager.top_shadow_color);argc++;
1220 	XtSetArg(args[argc], XmNmappedWhenManaged, False); argc++;
1221 
1222 	/* scrolling gets handled in the widget code itself, so don't set it */
1223 
1224 	/*
1225 	* Create when we have to, the widget is NULL or the widget isn't a
1226 	* XmHTML widget.
1227 	*/
1228 	if(fptr->doit == True || fptr->html == NULL)
1229 		widget = XmCreateHTML(HTML_ATTR(work_area), fptr->name, args, argc);
1230 	else if(!XmIsHTML(fptr->html))
1231 	{
1232 		/* not a HTML widget, spit out a warning and create one ourselves */
1233 		_XmHTMLWarning(__WFUNC__(fptr->html, "_XmHTMLFrameCreateCallback"),
1234 			XMHTML_MSG_60);
1235 		widget = XmCreateHTML(HTML_ATTR(work_area), fptr->name, args, argc);
1236 	}
1237 	else
1238 	{
1239 		widget = fptr->html;
1240 
1241 		/* first unmanage if it's still up */
1242 		if(tka->IsManaged(widget))
1243 			tka->UnmanageChild(widget);
1244 
1245 		/* check if we need to clear any existing source */
1246 		if(ATTR_HTML(widget, source) != NULL)
1247 		{
1248 			XtSetArg(args[argc], XmNvalue, NULL);
1249 			argc++;
1250 		}
1251 
1252 		/* reconfigure this widget so it'll fit our purposes */
1253 		XtSetValues(widget, args, argc);
1254 
1255 		/* unmanage scrollbars as well */
1256 		ATTR_HTML(widget, needs_vsb) = False;
1257 		ATTR_HTML(widget, needs_hsb) = False;
1258 		tka->UnmanageChild(ATTR_HTML(widget, hsb));
1259 		tka->UnmanageChild(ATTR_HTML(widget, vsb));
1260 	}
1261 
1262 	html_widget = (XmHTMLWidget)widget;
1263 	ATTR_HTML(html_widget, is_frame) = True;
1264 	ATTR_HTML(html_widget, frame_border) = frame->border;
1265 	ATTR_HTML(html_widget, scroll_type) = frame->scroll_type;
1266 
1267 	/* manage it */
1268 	tka->ManageChild(widget);
1269 
1270 	return(widget);
1271 }
1272 
1273 /*****
1274 * Name:			_XmHTMLCreateFrames
1275 * Return Type:	Boolean
1276 * Description:	main frame creator
1277 * In:
1278 *	html_old:	previous XmHTMLWidget id;
1279 *	html:		XmHTMLWidget id;
1280 * Returns:
1281 *	True when all frames could be created, False otherwise.
1282 *****/
1283 Boolean
_XmHTMLCreateFrames(XmHTMLWidget old,XmHTMLWidget html)1284 _XmHTMLCreateFrames(XmHTMLWidget old, XmHTMLWidget html)
1285 {
1286 	int i;
1287 	XmHTMLObject *tmp;
1288 	static Widget frame;
1289 
1290 	frame_stack = &frame_base;
1291 	frame_stack->next = NULL;
1292 	frame_stack->frame_set = NULL;
1293 
1294 	/* first destroy all previous frames of this widget */
1295 	if(old && old->html.nframes)
1296 		_XmHTMLDestroyFrames(old, old->html.nframes);
1297 
1298 	if(frame_sets)
1299 		destroyFrameSets(frame_sets);
1300 	frame_sets = NULL;
1301 
1302 	/*
1303 	* Don't do a thing if we are destroying the previous list, we don't have
1304 	* a frame callback or the new widget doesn't have any frames at all
1305 	*/
1306 	if(html == NULL || !html->html.frame_callback || html->html.nframes == 0)
1307 		return(False);
1308 
1309 	frame = NULL;
1310 
1311 	/* create the list of HTML frame childs */
1312 	html->html.frames = (XmHTMLFrameWidget**)calloc(html->html.nframes,
1313 		sizeof(XmHTMLFrameWidget*));
1314 
1315 	/* create individual HTML frame child ptrs */
1316 	for(i = 0; i < html->html.nframes; i++)
1317 	{
1318 		XmHTMLFrameWidget *frame_w;
1319 		frame_w = (XmHTMLFrameWidget*)malloc(sizeof(XmHTMLFrameWidget));
1320 		(void)memset(frame_w, 0, sizeof(XmHTMLFrameWidget));
1321 		html->html.frames[i] = frame_w;
1322 	}
1323 
1324 	/* move to the first frameset declaration */
1325 	for(tmp = html->html.elements; tmp != NULL && tmp->id != HT_FRAMESET;
1326 		tmp = tmp->next);
1327 
1328 	current_frame = 0;
1329 
1330 	/* create all frames (and possibly nested framesets also) */
1331 	makeFrameSets(html, tmp);
1332 
1333 	/* adjust framecount, makeFrameSets might have found some invalid sets */
1334 	html->html.nframes = current_frame;
1335 
1336 #ifdef DEBUG
1337 	_XmHTMLDebug(11, ("frames.c: _XmHTMLCreateFrames, raw frame listing\n"));
1338 	for(i = 0; i < html->html.nframes; i++)
1339 	{
1340 		_XmHTMLDebug(11, ("frame %i\n"
1341 			"\tname           : %s\n"
1342 			"\tsrc            : %s\n"
1343 			"\tsize           : %i\n",
1344 			i, html->html.frames[i]->src, html->html.frames[i]->name,
1345 			html->html.frames[i]->size_s));
1346 	}
1347 #endif
1348 
1349 	adjustConstraints(html);
1350 
1351 #ifdef DEBUG
1352 	_XmHTMLDebug(11, ("frames.c: _XmHTMLCreateFrames, adjusted frame "
1353 		"listing\n"));
1354 	for(i = 0; i < html->html.nframes; i++)
1355 	{
1356 		_XmHTMLDebug(11, ("frame %i\n"
1357 			"\tname           : %s\n"
1358 			"\tsrc            : %s\n"
1359 			"\twidth by height: %ix%i\n"
1360 			"\tx offset       : %i\n"
1361 			"\ty offset       : %i\n",
1362 			i, html->html.frames[i]->src, html->html.frames[i]->name,
1363 			html->html.frames[i]->width, html->html.frames[i]->height,
1364 			html->html.frames[i]->x, html->html.frames[i]->y));
1365 	}
1366 #endif
1367 	/* and now create all frames */
1368 	for(i = 0; i < html->html.nframes; i++)
1369 	{
1370 		html->html.frames[i]->frame = _XmHTMLFrameCreateCallback(html,
1371 			html->html.frames[i]);
1372 	}
1373 	/* erase a few glitches by calling adjustConstraints again */
1374 	_XmHTMLReconfigureFrames(html);
1375 
1376 	/* and now map them to screen */
1377 	mapFrames(html);
1378 
1379 	return(True);
1380 }
1381 
1382 /* doesn't work yet */
1383 #if 0
1384 void
1385 _XmHTMLDrawFrameBorder(XmHTMLWidget html)
1386 {
1387 	int x = html->core.x;
1388 	int y = html->core.y;
1389 	int width = html->html.frame_border;
1390 	int height = html->core.height;
1391 	Display *dsp = XtDisplay((Widget)html);
1392 	GC gc;
1393 	Window win = XtWindow((Widget)html);
1394 
1395 	gc = html->manager.bottom_shadow_GC;
1396 	XFillRectangle(dsp, win, gc, x, y, width, 1);
1397 	XFillRectangle(dsp, win, gc, x, y, 1, height-1);
1398 
1399 	gc = html->manager.top_shadow_GC;
1400 	XFillRectangle(dsp, win, gc, x+1, y + height-1, width-1, 1);
1401 	XFillRectangle(dsp, win, gc, x + width - 1, y + 1, 1, height-2);
1402 }
1403 #endif
1404 
1405 /********
1406 ****** Public XmHTML Functions
1407 ********/
1408 
1409 /*****
1410 * Name: 		XmHTMLFrameGetChild
1411 * Return Type: 	Widget
1412 * Description: 	returns the Widget id of a frame child given it's name.
1413 * In:
1414 *	w:			XmHTMLWidget
1415 *	name:		name of frame to locate.
1416 * Returns:
1417 *	If found, the widget id of the requested frame, NULL otherwise.
1418 *****/
1419 Widget
XmHTMLFrameGetChild(Widget w,String name)1420 XmHTMLFrameGetChild(Widget w, String name)
1421 {
1422 	XmHTMLWidget html;
1423 	int i;
1424 
1425 	/* sanity check */
1426 	if(!w || !XmIsHTML(w) || name == NULL)
1427 	{
1428 		String func = "FrameGetChild";
1429 		if(name == NULL)
1430 			_XmHTMLWarning(__WFUNC__(w, func),
1431 				XMHTML_MSG_21, "NULL frame name", func);
1432 		else
1433 			_XmHTMLBadParent(w, func);
1434 		return(NULL);
1435 	}
1436 
1437 	html = (XmHTMLWidget)w;
1438 
1439 	for(i = 0; i < html->html.nframes; i++)
1440 	{
1441 		if(!(strcmp(html->html.frames[i]->name, name)))
1442 			return(html->html.frames[i]->frame);
1443 	}
1444 	return(NULL);
1445 }
1446